<em id="09ttv"></em>
    <sup id="09ttv"><pre id="09ttv"></pre></sup>
    <dd id="09ttv"></dd>

        • NodeJS服務(wù)總是崩潰的解決辦法

          2020-3-23    seo達(dá)人

          許多人都有這樣一種映像,NodeJS比較快; 但是因為其是單線程,所以它不穩(wěn)定,有點(diǎn)不安全,不適合處理復(fù)雜業(yè)務(wù); 它比較適合對并發(fā)要求比較高,而且簡單的業(yè)務(wù)場景。 

          在Express的作者的TJ Holowaychuk的 告別Node.js一文中列舉了以下罪狀: 

          Farewell NodeJS (TJ Holowaychuk) 

          ?   you may get duplicate callbacks 
          ?   you may not get a callback at all (lost in limbo) 
          ?   you may get out-of-band errors 
          ?   emitters may get multiple “error” events 
          ?   missing “error” events sends everything to hell 
          ?   often unsure what requires “error” handlers 
          ?   “error” handlers are very verbose 
          ?   callbacks suck 

          其實(shí)這幾條主要吐嘈了兩點(diǎn): node.js錯誤處理很扯蛋,node.js的回調(diào)也很扯蛋。

           

           

          事實(shí)上呢?

           


          事實(shí)上NodeJS里程確實(shí)有“脆弱”的一面,單線程的某處產(chǎn)生了“未處理的”異常確實(shí)會導(dǎo)致整個Node.JS的崩潰退出,來看個例子, 這里有一個node-error.js的文件: 

           

          var http = require('http');
          
          var server = http.createServer(function (req, res) {
          
            //這里有個錯誤,params 是 undefined
            var ok = req.params.ok;
          
            res.writeHead(200, {'Content-Type': 'text/plain'});
            res.end('Hello World
          ');
          });
          
          server.listen(8080, '127.0.0.1');
          
          console.log('Server running at http://127.0.0.1:8080/');


          啟動服務(wù),并在地址欄測試一下發(fā)現(xiàn) http://127.0.0.1:8080/  不出所料,node崩潰了 


           

          $ node node-error
          Server running at http://127.0.0.1:8080/
          
          c:githubscript
          ode-error.js:5
            var ok = req.params.ok;
                               ^
          TypeError: Cannot read property 'ok' of undefined
              at Server.<anonymous> (c:githubscript
          ode-error.js:5:22)
              at Server.EventEmitter.emit (events.js:98:17)
              at HTTPParser.parser.onIncoming (http.js:2108:12)
              at HTTPParser.parserOnHeadersComplete [as onHeadersComplete] (http.js:121:23)
              at Socket.socket.ondata (http.js:1966:22)
              at TCP.onread (net.js:525:27)



           

          怎么解決呢?


          其實(shí)Node.JS發(fā)展到今天,如果連這個問題都解決不了,那估計早就沒人用了。 

           

          使用uncaughtException


          我們可以uncaughtException來全局捕獲未捕獲的Error,同時你還可以將此函數(shù)的調(diào)用棧打印出來,捕獲之后可以有效防止node進(jìn)程退出,如: 

           

          process.on('uncaughtException', function (err) {
            //打印出錯誤
            console.log(err);
            //打印出錯誤的調(diào)用棧方便調(diào)試
            console.log(err.stack);
          });


          這相當(dāng)于在node進(jìn)程內(nèi)部進(jìn)行守護(hù), 但這種方法很多人都是不提倡的,說明你還不能完全掌控Node.JS的異常。 

           

          使用 try/catch


          我們還可以在回調(diào)前加try/catch,同樣確保線程的安全。 

           

          var http = require('http');
          
          http.createServer(function(req, res) {
            try {
              handler(req, res);
            } catch(e) {
              console.log('
          ', e, '
          ', e.stack);
              try {
                res.end(e.stack);
              } catch(e) { }
            }
          }).listen(8080, '127.0.0.1');
          
          console.log('Server running at http://127.0.0.1:8080/');
          
          var handler = function (req, res) {
            //Error Popuped
            var name = req.params.name;
          
            res.writeHead(200, {'Content-Type': 'text/plain'});
            res.end('Hello ' + name);
          };


          這種方案的好處是,可以將錯誤和調(diào)用棧直接輸出到當(dāng)前發(fā)生的網(wǎng)頁上。 

           

          集成到框架中


          標(biāo)準(zhǔn)的HTTP響應(yīng)處理會經(jīng)歷一系列的Middleware(HttpModule),最終到達(dá)Handler,如下圖所示: 

          \ 


          這 些Middleware和Handler在NodeJS中都有一個特點(diǎn),他們都是回調(diào)函數(shù),而回調(diào)函數(shù)中是唯一會讓Node在運(yùn)行時崩潰的地方。根據(jù)這個 特點(diǎn),我們只需要在框架中集成一處try/catch就可以相對完美地解決異常問題,而且不會影響其它用戶的請求request。 

          事實(shí)上現(xiàn)在的NodeJS WEB框架幾乎都是這么做的,如 OurJS開源博客所基于的 WebSvr 

          就有這么一處異常處理代碼: 

           

          Line: 207
          
            try {
              handler(req, res);
            } catch(err) {
              var errorMsg
                = '
          '
                + 'Error ' + new Date().toISOString() + ' ' + req.url
                + '
          '
                + err.stack || err.message || 'unknow error'
                + '
          '
                ;
          
              console.error(errorMsg);
              Settings.showError
                ? res.end('<pre>' + errorMsg + '</pre>')
                : res.end();
            }


          那么不在回調(diào)中產(chǎn)生的錯誤怎么辦?不必?fù)?dān)心,其實(shí)這樣的node程序根本就起不起來。 

          此外node自帶的 cluster 也有一定的容錯能力,它跟nginx的worker很類似,但消耗資源(內(nèi)存)略大,編程也不是很方便,OurJS并沒有采用此種設(shè)計。 

           

          守護(hù)NodeJS進(jìn)程和記錄錯誤日志


          現(xiàn) 在已經(jīng)基本上解決了Node.JS因異常而崩潰的問題,不過任何平臺都不是100%可靠的,還有一些錯誤是從Node底層拋出的,有些異常 try/catch和uncaughtException都無法捕獲。之前在運(yùn)行ourjs的時侯,會偶爾碰到底層拋出的文件流讀取異常,這就是一個底層 libuv的BUG,node.js在0.10.21中進(jìn)行了修復(fù)。 

          面對這種情況,我們就應(yīng)該為nodejs應(yīng)用添加守護(hù)進(jìn)程,讓NodeJS遭遇異常崩潰以后能馬上復(fù)活。 

          另外,還應(yīng)該把這些產(chǎn)生的異常記錄到日志中,并讓異常永遠(yuǎn)不再發(fā)生。 

           

          使用node來守護(hù)node


          node-forever 提供了守護(hù)的功能和LOG日志記錄功能。 

          安裝非常容易 

           

          [sudo] npm install forever


          使用也很簡單 

           

          $ forever start simple-server.js
          $ forever list
            [0] simple-server.js [ 24597, 24596 ]


          還可以看日志 

           

          forever -o out.log -e err.log my-script.js


           

          使用shell啟動腳本守護(hù)node


          使用node來守護(hù)的話資源開銷可能會有點(diǎn)大,而且也會略顯復(fù)雜,OurJS直接在開機(jī)啟動腳本來進(jìn)程線程守護(hù)。 

          如在debian中放置的 ourjs 開機(jī)啟動文件: /etc/init.d/ourjs 

          這個文件非常簡單,只有啟動的選項,守護(hù)的核心功能是由一個無限循環(huán) while true; 來實(shí)現(xiàn)的,為了防止過于密集的錯誤阻塞進(jìn)程,每次錯誤后間隔1秒重啟服務(wù) 

           

          WEB_DIR='/var/www/ourjs'
          WEB_APP='svr/ourjs.js'
          
          #location of node you want to use
          NODE_EXE=/root/local/bin/node
          
          while true; do
              {
                  $NODE_EXE $WEB_DIR/$WEB_APP config.magazine.js
                  echo "Stopped unexpected, restarting 
          
          "
              } 2>> $WEB_DIR/error.log
              sleep 1
          done


           

          錯誤日志記錄也非常簡單,直接將此進(jìn)程控制臺當(dāng)中的錯誤輸出到error.log文件即可: 2>> $WEB_DIR/error.log  這一行, 2 代表 Error。

          日歷

          鏈接

          個人資料

          存檔

          欧美久久久久久精选9999| 2021国产精品久久精品| 99久久超碰中文字幕伊人| 99精品久久精品| 久久久受www免费人成| 久久久久亚洲精品天堂| 成人国内精品久久久久影院VR | 亚洲精品无码久久久久去q| 午夜精品久久久久久毛片| 精品久久久久久无码中文野结衣| 久久久久久久久波多野高潮| 99久久精品免费看国产免费| 色综合久久无码中文字幕| 久久久久国产视频电影| 粉嫩小泬无遮挡久久久久久| 日本五月天婷久久网站| 国产精品免费久久久久影院| 久久99久久99精品免视看动漫| 亚洲国产精品一区二区三区久久 | 97精品依人久久久大香线蕉97| 久久亚洲精品视频| 久久精品午夜一区二区福利| 欧美一区二区久久精品| 久久婷婷人人澡人人| 久久99热这里只有精品国产 | 久久99精品久久久久久hb无码 | 亚洲日本va午夜中文字幕久久| 天天爽天天爽天天片a久久网| 激情伊人五月天久久综合| 欧美亚洲国产精品久久高清 | 少妇久久久久久久久久| 精品久久久一二三区| 国产精品久久新婚兰兰| 亚洲?V乱码久久精品蜜桃| 麻豆久久| 精品一二三区久久aaa片| 伊人久久精品无码二区麻豆| 7777久久久国产精品消防器材 | 囯产极品美女高潮无套久久久| 久久久无码精品亚洲日韩蜜臀浪潮 | 日本精品久久久久中文字幕|