被吐嘈的NodeJS的異常處理

?

被吐嘈的NodeJS的異常處理


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

在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?

其實這幾條主要吐嘈了兩點: node.js錯誤處理很扯蛋,node.js的回調也很扯蛋。?

事實上呢?


事實上NodeJS里程確實有“脆弱”的一面,單線程的某處產生了“未處理的”異常確實會導致整個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\n'); }); server.listen(8080, '127.0.0.1'); console.log('Server running at http://127.0.0.1:8080/');


啟動服務,并在地址欄測試一下發現?http://127.0.0.1:8080/? 不出所料,node崩潰了?


$ node node-error
Server running at http://127.0.0.1:8080/c:\github\script\node-error.js:5 var ok = req.params.ok; ^ TypeError: Cannot read property 'ok' of undefined at Server.<anonymous> (c:\github\script\node-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)



怎么解決呢?


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

使用uncaughtException


我們可以uncaughtException來全局捕獲未捕獲的Error,同時你還可以將此函數的調用棧打印出來,捕獲之后可以有效防止node進程退出,如:?

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


這相當于在node進程內部進行守護, 但這種方法很多人都是不提倡的,說明你還不能完全掌控Node.JS的異常。?

使用 try/catch


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

var http = require('http');http.createServer(function(req, res) { try { handler(req, res); } catch(e) { console.log('\r\n', e, '\r\n', 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); };


這種方案的好處是,可以將錯誤和調用棧直接輸出到當前發生的網頁上。?

集成到框架中


標準的HTTP響應處理會經歷一系列的Middleware(HttpModule),最終到達Handler,如下圖所示:?

?


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

事實上現在的NodeJS WEB框架幾乎都是這么做的,如?OurJS開源博客所基于的?WebSvr?

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

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


那么不在回調中產生的錯誤怎么辦?不必擔心,其實這樣的node程序根本就起不起來。?

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

守護NodeJS進程和記錄錯誤日志


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

面對這種情況,我們就應該為nodejs應用添加守護進程,讓NodeJS遭遇異常崩潰以后能馬上復活。?

另外,還應該把這些產生的異常記錄到日志中,并讓異常永遠不再發生。?

使用node來守護node


node-forever?提供了守護的功能和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啟動腳本守護node


使用node來守護的話資源開銷可能會有點大,而且也會略顯復雜,OurJS直接在開機啟動腳本來進程線程守護。?

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

這個文件非常簡單,只有啟動的選項,守護的核心功能是由一個無限循環 while true; 來實現的,為了防止過于密集的錯誤阻塞進程,每次錯誤后間隔1秒重啟服務?

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 \r\n\r\n" ??? } 2>> $WEB_DIR/error.log ??? sleep 1 done

?

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

?

轉自:?OurJS

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/394358.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/394358.shtml
英文地址,請注明出處:http://en.pswp.cn/news/394358.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

javascript關鍵字_讓我們揭開JavaScript的“ new”關鍵字的神秘面紗

javascript關鍵字by Cynthia Lee辛西婭李(Cynthia Lee) 讓我們揭開JavaScript的“ new”關鍵字的神秘面紗 (Let’s demystify JavaScript’s ‘new’ keyword) Over the weekend, I completed Will Sentance’s JavaScript: The Hard Parts. It might not sound like the most…

查看 rabbitmq 啟動websocket 提示404_RabbitMQ在windows下安裝(筆記)

先保證Java開發環境一切正常&#xff0c;【jdk,maven】,然后下載兩個文件&#xff0c;1&#xff0c;下載OTPhttps://www.rabbitmq.com/download.html 下載地址下載RabbitMQ Downloading and Installing RabbitMQ:地址安裝沒有別的操作&#xff0c;一直下一步就好&#xff1b;2&…

[Leetcode] Longest Valid Parentheses

找出字串裡最長的合法括號組 簡單說&#xff0c;一樣stack搜尋合法parenth&#xff0c;把不合法的 ( & ) index 紀錄下來&#xff0c;最後算index間的差值取最大就是最長的 public class Solution{/// <summary>/// 把不合法的( )的index記下來&#xff0c;取最長的差…

leetcode35. 搜索插入位置(二分搜索)

給定一個排序數組和一個目標值&#xff0c;在數組中找到目標值&#xff0c;并返回其索引。如果目標值不存在于數組中&#xff0c;返回它將會被按順序插入的位置。 你可以假設數組中無重復元素。 示例 1: 輸入: [1,3,5,6], 5 輸出: 2 代碼 class Solution {public int sear…

[deviceone開發]-do_Album的簡單示例

一、簡介do_Album用來打開手機系統提供的相冊&#xff0c;能選擇一張或多張圖片返回給開發者&#xff0c;通常相冊的圖片比較大&#xff0c;要經過縮放。有的時候用戶也需要把別的地方獲取到到圖片收藏到系統相冊。這個示例簡單展示這個組件的2個基本功能。二、效果圖三、相關下…

公辦低分二本_這六所公辦二本高校的計算機類相關專業值得低分段考生選擇

邯鄲學院——計算機科學與技術近年來&#xff0c;邯鄲學院著力強化“以本為本”理念,堅持“學生中心”“產出導向”原則&#xff0c;加強學科專業建設&#xff0c;獲批國家級特色專業1個&#xff0c;省級重點發展學科3個&#xff0c;省級一流專業7個&#xff0c;英語等3個專業入…

用戶體驗改善案例_用戶體驗案例研究:建立更好的體驗(重新設計“和平航空”網站)...

用戶體驗改善案例by Peace Ojemeh (Perrie)由Peace Ojemeh(Perrie) 用戶體驗案例研究&#xff1a;建立更好的體驗(重新設計“和平航空”網站) (A UX case study: Building a better experience (Re-designing the Air Peace Airline website)) Traveling by air is always an …

[轉]FFMPEG調節音頻的音量大小,混音

鏈接&#xff1a;https://blog.csdn.net/nil_lu/article/details/52078488 轉載于:https://www.cnblogs.com/zifeiy/p/10675734.html

局域網即時通訊軟件_無線局域網中,安卓手機和電腦的資源如何實現互傳互訪?...

安卓手機和電腦之間的資源共享&#xff0c;可實現的方案有很多&#xff0c;例如&#xff1a;方案一是各種官方或第三方出品的“XX手機助手”軟件。優點是直連的傳輸速率最高&#xff1b;缺點一是手機和電腦必須連在一起&#xff0c;相當不方便&#xff0c;缺點二是萬一中途發生…

leetcode516. 最長回文子序列(動態規劃)

***給定一個字符串 s &#xff0c;找到其中最長的回文子序列&#xff0c;并返回該序列的長度。***可以假設 s 的最大長度為 1000 。 示例 1: 輸入: “bbbab” 輸出: 4 一個可能的最長回文子序列為 “bbbb”。 解題思路 數組含義&#xff1a;dp[i][j]子串&#xff08;i&#…

Ubuntu 14.04 FTP服務器--vsftpd的安裝和配置

更新源列表 打開"終端窗口"&#xff0c;輸入"sudo apt-get update"-->回車-->"輸入當前登錄用戶的管理員密碼"-->回車,就可以了。如果不運行該命令&#xff0c;直接安裝vsftpd,會出現"有 幾個軟件包無法下載&#xff0c;您可以運…

校驗電話號碼 手機號碼正則表達式

2019獨角獸企業重金招聘Python工程師標準>>> 電話號碼 手機號碼 等準確詳細 正則表達式電話號碼正則表達式 &#xff08;支持手機號碼&#xff0c;3-4位區號&#xff0c;7-8位直播號碼&#xff0c;1&#xff0d;4位分機號&#xff09; ((\d{11})|^((\d{7,8})|(\d{4}…

期刊投稿狀態_SCI投稿全過程解析及拒稿后處理對策

之前給大家介紹了如果使用人工智能來提高SCI寫作效率的神器&#xff0c;相信大家對SCI寫作已經很有信心了。但有些小伙伴后臺說對投稿過程很沒有概念&#xff0c;不同期刊不同狀態。那么今天我們就對SCI投稿過程、投稿狀態做一個總結和解析以及拒稿后處理對策及接受后期相關問答…

cake php_如何(以及為什么)在Swinject中使用Cake Pattern

cake phpby Peter-John Welcome由Peter-John Welcome 如何(以及為什么)在Swinject中使用Cake Pattern (How (and why) to use the Cake Pattern with Swinject) In my previous article, I showed how we can use the Cake Pattern to do dependency injection without any li…

運用Appium 實現添加微信好友自動化

本文為原創文章&#xff0c;如需轉載請注明出處. 任務&#xff1a;實現批量添加微信好友自動化。 任務分析&#xff1a;1.首先要實現添加單個好友步驟自動化。 2.實現腳本讀取Excel里的值。 3.參數化好友電話號碼或者昵稱。 PS:代碼采用POM(Page Object Model)便于后續維護 數…

pdf.js瀏覽中文pdf亂碼的問題解決

由于項目中需要支持移動設備在線瀏覽pdf&#xff0c;蘋果還好&#xff0c;天生支持&#xff0c;但是安卓中就不行了&#xff0c;需要第三方組件的支持。 這里就找到了pdf.js&#xff0c;由于pdf數據太多&#xff0c;開始的時候沒法一一測試&#xff0c;所以隨便測試打開了幾篇沒…

python導入sas數據集_運用import過程進行SAS數據導入完全實用教程

運用import過程進行SAS數據導入完全實用教程1 單個規范格式文件導入。對單個文件進行導入是我們遇到最多的情況&#xff0c;主要有以下幾種&#xff1a;1.1 對指定分隔符(’|’&#xff0c;’’&#xff0c;’!’&#xff0c;’ab’等)數據的導入&#xff0c;這里以’!’為例de…

【效率專精系列】善用API統一描述語言提升RestAPI開發效率

團隊內部RestAPI開發采用設計驅動開發的模式&#xff0c;即使用API設計文檔解耦前端和后端的開發過程&#xff0c;雙方只在聯調與測試時耦合。在實際開發和與前端合作的過程中&#xff0c;受限于眾多因素的影響&#xff0c;開發效率還有進一步提高的空間。本文的目的是優化工具…

leetcode劍指 Offer 14- I. 剪繩子(動態規劃)

給你一根長度為 n 的繩子&#xff0c;請把繩子剪成整數長度的 m 段&#xff08;m、n都是整數&#xff0c;n>1并且m>1&#xff09;&#xff0c;每段繩子的長度記為 k[0],k[1]…k[m-1] 。請問 k[0]k[1]…*k[m-1] 可能的最大乘積是多少&#xff1f;例如&#xff0c;當繩子的…

數據包提取文件_航測怎樣高效提取無人機POS航點數據

無限創新工作室研發的POS數據記錄儀是一款采集飛控POS 數據并管理的設備&#xff0c;它將飛控 POS 點數據進行記錄&#xff0c;形成單獨的POS 數據記錄TXT 文本&#xff0c;并獨立存儲于內存卡&#xff0c;可通過USB、U 盤或內存卡形式對數據進行讀取。通過對相機進行拍照控制和…