偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

一年Node.js開(kāi)發(fā)開(kāi)發(fā)經(jīng)驗(yàn)總結(jié)

開(kāi)發(fā) 前端
本文總結(jié)了Node.js開(kāi)發(fā)一年多以來(lái)的實(shí)踐總結(jié)等。Node.js的開(kāi)發(fā)與前端網(wǎng)頁(yè)的開(kāi)發(fā)思路不同,著重點(diǎn)不一樣。我正式開(kāi)發(fā)Node.js的時(shí)間也不算太長(zhǎng),一些點(diǎn)并沒(méi)有深入的理解,本文僅僅是一些經(jīng)驗(yàn)之談。

寫(xiě)在前面

不知不覺(jué)的,寫(xiě)Node.js已經(jīng)一年了。不同于最開(kāi)始的demo、本地工具等,這一年里,都是用Node.js寫(xiě)的線上業(yè)務(wù)。從一開(kāi)始的Node.js同構(gòu)直出,到最近的Node接入層,也算是對(duì)Node開(kāi)發(fā)入門(mén)了吧。目前,我一個(gè)人維護(hù)了大部分組內(nèi)流傳下來(lái)的Node服務(wù),包括內(nèi)部系統(tǒng)和線上服務(wù)。新增的后臺(tái)服務(wù),也是盡可能地使用Node進(jìn)行開(kāi)發(fā)。本文是一下自己最近的一些小小的總結(jié)和思考。

本文不會(huì)深入講解Node.js本身的特性,架構(gòu)等等。我也沒(méi)有寫(xiě)過(guò)Node擴(kuò)展或者庫(kù)什么的,對(duì)Node.js的了解也并不夠深入。

為何用Node

對(duì)于我來(lái)說(shuō),對(duì)于團(tuán)隊(duì)來(lái)說(shuō),適用Node的原因其實(shí)很簡(jiǎn)單:開(kāi)發(fā)起來(lái)快。熟悉JS的前端同學(xué)可以很快上手,節(jié)省成本。選一個(gè)http server庫(kù)起一個(gè)server,選擇合適的中間件,匹配好請(qǐng)求路由,看情況合理使用ORM庫(kù)鏈接數(shù)據(jù)庫(kù)、增刪改查即可。

Node的適用場(chǎng)景

Node.js 使用了一個(gè)事件驅(qū)動(dòng)、非阻塞式 I/O 的模型,使其輕量又高效。這種模型使得Node.js 可以避免了由于需要等待輸入或者輸出(數(shù)據(jù)庫(kù)、文件系統(tǒng)、Web服務(wù)器...)響應(yīng)而造成的 CPU 時(shí)間損失。所以,Node.js適合運(yùn)用在高并發(fā)、I/O密集、少量業(yè)務(wù)邏輯的場(chǎng)景。

對(duì)應(yīng)到平時(shí)具體的業(yè)務(wù)上,如果是內(nèi)部的系統(tǒng),大部分僅僅就是需要對(duì)某個(gè)數(shù)據(jù)庫(kù)進(jìn)行增刪改查,那么Server端直接就是Node.js一把梭。

對(duì)于線上業(yè)務(wù),如果流量不大,并且業(yè)務(wù)邏輯簡(jiǎn)單的情況下,Server端也可以完全使用Node.js。對(duì)于流量巨大,復(fù)雜度高的項(xiàng)目,一般用Node.js作為接入層,后臺(tái)同學(xué)負(fù)責(zé)實(shí)現(xiàn)服務(wù)。如下圖:

同樣是寫(xiě)JS,Node.js開(kāi)發(fā)和頁(yè)面開(kāi)發(fā)有什么區(qū)別

在瀏覽器端開(kāi)發(fā)頁(yè)面,是和用戶(hù)打交道、重交互,瀏覽器還提供了各種Web Api供我們使用。Node.js主要面向數(shù)據(jù),收到請(qǐng)求后,返回具體的數(shù)據(jù)。這是兩者在業(yè)務(wù)路徑上的區(qū)別。而真正的區(qū)別其實(shí)是在于業(yè)務(wù)模型上(業(yè)務(wù)模型,這是我自己瞎想的一個(gè)詞)。直接用圖表示吧。

開(kāi)發(fā)頁(yè)面時(shí),每一個(gè)用戶(hù)的瀏覽器上都有一份JS代碼。如果代碼在某種情況下崩了,只會(huì)對(duì)當(dāng)前用戶(hù)產(chǎn)生影響,并不會(huì)影響其他用戶(hù),用戶(hù)刷新一下即可恢復(fù)。而在Node.js中,在不開(kāi)啟多進(jìn)程的情況下,所有用戶(hù)的請(qǐng)求,都會(huì)走進(jìn)同一份JS代碼,并且只有一個(gè)線程在執(zhí)行這份JS代碼。如果某個(gè)用戶(hù)的請(qǐng)求,導(dǎo)致發(fā)生錯(cuò)誤,Node.js進(jìn)程掛掉,server端直接就掛了。盡管可能有進(jìn)程守護(hù),掛掉的進(jìn)程會(huì)被重啟,但是在用戶(hù)請(qǐng)求量大的情況下,錯(cuò)誤會(huì)被頻繁觸發(fā),可能就會(huì)出現(xiàn)server端不停掛掉,不停重啟的情況,對(duì)用戶(hù)體驗(yàn)造成影響。

以上,可能是Node.js開(kāi)發(fā)和前端JS開(kāi)發(fā)最大的區(qū)別。

Node.js開(kāi)發(fā)時(shí)的注意事項(xiàng)

用戶(hù)在訪問(wèn)Node.js服務(wù)時(shí),如果某一個(gè)請(qǐng)求卡住了,服務(wù)遲遲不能返回結(jié)果,或者說(shuō)邏輯出錯(cuò),導(dǎo)致服務(wù)掛掉,都會(huì)帶來(lái)大規(guī)模的體驗(yàn)問(wèn)題。server端的目標(biāo),就是要 快速、可靠 地返回?cái)?shù)據(jù)。

  • 緩存

由于Node.js不擅長(zhǎng)處理復(fù)雜邏輯(JavaScript本身執(zhí)行效率較低),如果要用Node.js做接入層,應(yīng)該避免復(fù)雜的邏輯。想要快速處理數(shù)據(jù)并返回,一個(gè)至關(guān)重要的點(diǎn):使用緩存。

例如,使用Node做React同構(gòu)直出,renderToString這個(gè)Api,可以說(shuō)是比較重的邏輯了。如果頁(yè)面的復(fù)雜度高,每次請(qǐng)求都完整執(zhí)行renderToString,會(huì)長(zhǎng)時(shí)間占用線程來(lái)執(zhí)行代碼,增加響應(yīng)時(shí)間,降低服務(wù)的吞吐量。這個(gè)時(shí)候,緩存就十分重要了。

實(shí)現(xiàn)緩存的主要方式:內(nèi)存緩存。可以使用Map,WeakMap,WeakRef等實(shí)現(xiàn)。參考以下簡(jiǎn)單的示例代碼: 

  1. const cache = new Map();  
  2. router.get('/getContent', async (req, res) => {  
  3.   const id = req.query.id; 
  4.    // 命中緩存  
  5.   if(cache.get(id)) {  
  6.     return res.send(cache.get(id));  
  7.   }  
  8.    // 請(qǐng)求數(shù)據(jù)  
  9.   const rsp = await rpc.get(id);  
  10.      // 經(jīng)過(guò)一頓復(fù)雜的操作,處理數(shù)據(jù)  
  11.   const content = process(rsp);  
  12.   // 設(shè)置緩存  
  13.   cache.set(id, content); 
  14.    return res.send(content);  
  15. }); 

使用緩存時(shí),有一個(gè)很重要的問(wèn)題是:內(nèi)存緩存如何更新。一種最簡(jiǎn)單的方法,開(kāi)一個(gè)定時(shí)器,定期刪除緩存,下一次請(qǐng)求到來(lái)時(shí),重新設(shè)置緩存即可。在上述代碼中,增加如下代碼: 

  1. setTimeout(function() {  
  2.   cache.clear();  
  3. }, 1000 * 60); // 1分鐘刪除一次緩存 

如果server端完全使用Node實(shí)現(xiàn),需要用Node端直接連接數(shù)據(jù)庫(kù),在數(shù)據(jù)時(shí)效性要求不太高、且流量不太大的情況下,就可以使用上述類(lèi)似的模型,如下圖。這樣可以降低數(shù)據(jù)庫(kù)的壓力且加快Node的響應(yīng)速度。

另外,還需要注意內(nèi)存緩存的大小。如果一直往緩存里寫(xiě)入新數(shù)據(jù),那么內(nèi)存會(huì)越來(lái)越大,最終爆掉。可以考慮使用LRU(Least Recently Used)算法來(lái)做緩存。開(kāi)辟一塊內(nèi)存專(zhuān)門(mén)作為緩存區(qū)域。當(dāng)緩存大小達(dá)到上限時(shí),淘汰最久未使用的緩存。

內(nèi)存緩存會(huì)隨著進(jìn)程的重啟而全部失效。

當(dāng)后臺(tái)業(yè)務(wù)比較復(fù)雜,接入層流量,數(shù)據(jù)量較大時(shí),可以使用如下的架構(gòu),使用獨(dú)立的內(nèi)存緩存服務(wù)。Node接入層直接從緩存服務(wù)取數(shù)據(jù),后臺(tái)服務(wù)直接更新緩存服務(wù)。

當(dāng)然,上圖中的架構(gòu)是最簡(jiǎn)單的情形,現(xiàn)實(shí)中還需要考慮分布式緩存、緩存一致性的問(wèn)題。這又是另外一個(gè)話題了。

  • 錯(cuò)誤處理

由于Node.js語(yǔ)言的特性,Node服務(wù)是比較容易出錯(cuò)的。而一旦出錯(cuò),造成的影響就是服務(wù)不可用。因此,對(duì)于錯(cuò)誤的處理十分的重要。

處理錯(cuò)誤,最常用的就是try catch 了??墒?try catch無(wú)法捕獲異步錯(cuò)誤。Node.js中,異步操作是十分常見(jiàn)的,異步操作主要是在回調(diào)函數(shù)中暴露錯(cuò)誤??匆粋€(gè)例子: 

  1. const readFile = function(path) {  
  2.     return new Promise((resolve,reject) => {  
  3.         fs.readFile(path, (err, data) => {  
  4.             if(err) {   
  5.                 throw err; // catch無(wú)法捕獲錯(cuò)誤,這和Node的eventloop有關(guān)。  
  6.         // reject(err); // catch可以捕獲  
  7.       }  
  8.       resolve(data);  
  9.         });  
  10.     });  
  11. router.get('/xxx', async function(req, res) {  
  12.   try {  
  13.     const res = await readFile('xxx');  
  14.     ...  
  15.   } catch (e){  
  16.     // 捕獲錯(cuò)誤處理  
  17.     ...  
  18.     res.send(500);  
  19.   }  
  20. }); 

上面的代碼中,readFile 中 throw 出來(lái)的錯(cuò)誤,是無(wú)法被catch捕獲的。如果我們把 throw err 換成 Promise.reject(err),catch中是可以捕獲到錯(cuò)誤的。

我們可以把異步操作都Promise化,然后統(tǒng)一使用 async 、try、catch 來(lái)處理錯(cuò)誤。

但是,總會(huì)有地方會(huì)被遺漏。這個(gè)時(shí)候,可以使用process來(lái)捕獲全局錯(cuò)誤,防止進(jìn)程直接退出,導(dǎo)致后面的請(qǐng)求掛掉。示例代碼: 

  1. process.on('uncaughtException', (err) => {  
  2.   console.error(`${err.message}\n${err.stack}`);  
  3. });  
  4. process.on('unhandledRejection', (reason, p) => {  
  5.   console.error(`Unhandled Rejection at: Promise ${p} reason: `, reason); 
  6.  }); 

關(guān)于Node.js中錯(cuò)誤的捕獲,還可以使用domain模塊。現(xiàn)在這個(gè)模塊已經(jīng)不推薦使用了,我也沒(méi)有在項(xiàng)目中實(shí)踐過(guò),這里就不展開(kāi)了。Node.js 近幾年推出的 async_hooks 模塊,也還處于實(shí)驗(yàn)階段,不太建議線上環(huán)境直接使用。做好進(jìn)程守護(hù),開(kāi)啟多進(jìn)程,錯(cuò)誤告警及時(shí)修復(fù),養(yǎng)成良好的編碼規(guī)范,使用合適的框架,才能提高Node服務(wù)的效率及穩(wěn)定性。

寫(xiě)在后面

本文總結(jié)了Node.js開(kāi)發(fā)一年多以來(lái)的實(shí)踐總結(jié)等。Node.js的開(kāi)發(fā)與前端網(wǎng)頁(yè)的開(kāi)發(fā)思路不同,著重點(diǎn)不一樣。我正式開(kāi)發(fā)Node.js的時(shí)間也不算太長(zhǎng),一些點(diǎn)并沒(méi)有深入的理解,本文僅僅是一些經(jīng)驗(yàn)之談。 

 

責(zé)任編輯:龐桂玉 來(lái)源: segmentfault
相關(guān)推薦

2010-01-26 13:28:11

Android開(kāi)發(fā)要點(diǎn)

2015-03-10 10:59:18

Node.js開(kāi)發(fā)指南基礎(chǔ)介紹

2017-01-05 16:29:00

2012-09-29 11:13:15

Node.JS前端開(kāi)發(fā)Node.js打包

2010-01-14 16:14:15

VB.NET界面設(shè)計(jì)

2019-02-28 10:52:44

Shell運(yùn)維經(jīng)驗(yàn)

2014-02-14 10:48:32

Visual StudNode.js

2022-01-07 08:00:00

Node.js開(kāi)發(fā)Web

2009-10-15 09:27:00

2011-11-10 11:08:34

Node.js

2013-05-17 09:41:02

Node.js云應(yīng)用開(kāi)發(fā)IaaS

2014-08-01 09:57:52

Node.jsNode.js插件

2021-01-14 10:48:34

Docker CompNode.js開(kāi)發(fā)

2015-09-14 15:13:52

2013-07-11 14:41:16

編程經(jīng)驗(yàn)

2015-07-15 10:32:44

Node.js命令行程序

2021-12-28 20:04:23

Node.js開(kāi)發(fā)JavaScript

2011-11-30 11:32:37

Node.js

2014-08-15 09:36:06

2023-11-08 08:23:28

Node版本
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)