被吐嘈的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.mzph.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 盘或内存卡形式对数据进行读取。通过对相机进行拍照控制和…