likes
comments
collection
share

关于NodeJS系统稳定的一些思考

作者站长头像
站长
· 阅读数 16

前言

在我们日常开发中,因为前端某些用户操作的边缘性场景,导致逻辑Bug造成用户服务异常,但是我们在服务端有没有做好异常保护,这就可能导致整个进程退出,从而无法提供服务,因此在考虑如何做好监控和进程保护对系统稳定就很重要。那么我们在Node.js代码层面应该如何降低异常出现的概率呢?

为什么要做这种思考?

首先,举一个例子,我们家中的电路保护措施,一般情况下家庭的每一部分线路都会有短路跳闸机制。如果我们不考虑安全保护措施,这就会由于一个线路问题导致家庭整体电路瘫痪。

在Node.js服务中,会由于一个用户的异常访问或者数据异常,加上没有做好异常处理和安全保护,直接就会导致整个Node.js服务重启,从而中断所有人的请求,用户体验非常差。

因此,我们要尽可能地在最小处进行安全保护,这样就最小地影响用户,比如用户数据异常,只会影响该用户,而不会影响整个服务的其他用户。

哪些场景会导致Node.js异常?

  • 由于Node.js使用的是JavaScript,而JavaScript是弱类型语言,在生产环境经常会引发一些由于代码逻辑的异常导致进程异常退出。

  • 其次在Node.js中也经常会因为内存使用不当,导致内存泄露,当处于64位操作系统中内存超过1.4G(32位操作系统超过0.7G)会导致垃圾回收时间超过1s,导致回收缓慢,进而造成内存泄露,Node.js就会奔溃。

  • Node.js以IO密集型为优势, 因此当我们启动较多的I/O句柄, 但是没有及时释放,同样会造成进程问题

这些都会导致服务器异常退出,无法提供正常服务,从而引发生成环境问题

考虑代码异常的场景如下:

关于NodeJS系统稳定的一些思考

null.property

如果没有对数据进行严格的判断就进行逻辑处理,会导致代码服务异常退出,从而影响用户体验。

首先第一种多层数据嵌套查找(data.str.str),需要逐层进行数据判断,当data.str置null时,则data.str.str就会报错,因此在这里就无法处理。这种问题一般会导致进程退出,但是在源码中做了保护,不会退出。

因此当我们的数据结构比较复杂的时候,判断逻辑也会复杂,从而影响开发效率,因此可以采用lodash真个库方便操作数据。

parameters error

首先我们一般使用JSON.parse()的时候都是从其他地方获取到数据进行解析,但是有时候这些数据非JSON字符串,就会引发异常。因此我们需要通过try catch异常捕捉判断

其中fs常会因为权限不足,或者文件不存在等问题。

other errors

由于Node.js时运行时报错,因此愈发问题也只会在运行期间被发现,例如常见的同变量名重复声明。

还有一些长连接服务,例如Socket、Redis、Memcache等, 我们需要在连接异常的时候进行处理,如果没有处理同样会导致异常,比如Socket提供了Socket.on('error')的监听

常见服务异常解析

服务器异常在Node.js中最常见的问题主要是内存泄露句柄泄露以及网络模块的调用。

实际开发中常见场景如下:

全局变量

一般情况下不建议使用全局变量,因为全局变量时最容易引发内存泄露问题的, 我们要将用户的session保存在一个全局变量中,随着用户越来越多,这个session变量保存的数据也会越来大,会影响内存的大小。并且这种全局变量必须要有一定的上限和清理规则才能保证服务的安全。

单例模式中变量和对象

例如当前封装有一个axios请求,当使用了单例模式之后,每次请求之后都会多创建一个对象,并且不会被主动释放,除非重启

打开文件后,未主动关闭

当我们一帮打开文件句柄后,我们都会主动关闭,如果未主动关闭就会导致文件句柄越来越多,从而引发句柄泄露问题。

在Node.js中fs的模块中都提供了打开文件句柄关闭的方法,比如fs.open提供了fs.close的方法,其次比如fs.createWriteStream提供了fileStream.end的方法。

网络句柄

当我们重复调用第三方接口, 特别是在使用Node.js第三方库request以及Socket模块。

拓展

  • 设计系统异常处理, 并全局捕捉未处理的异常。
  • 进程异常问题,通过使用pm2构建服务,专门搭建一个监控告警机制。

监控告警服务学习中...

转载自:https://juejin.cn/post/7231539903649169467
评论
请登录