Nodejs在高并发下的性能优化,各位有哪些好的建议吗?

发布于 1周前 作者 sinazl 来自 nodejs/Nestjs

Nodejs在高并发下的性能优化,各位有哪些好的建议吗?

公司业务需要用 node 转发微信消息给其他后端服务器,每次推送 20W 模板消息, node 会收到 TEMPLATESENDJOBFINISH 的消息回复

一开始和这个问题的情况类似,逻辑很简单,就接受消息转发消息,也是用 request 发送消息,并发量一大后面的请求处理时间就很长,导致经常 5s 内无法响应微信服务器进而报警。后来查了半天发现 node 默认线程池只有 4 个线程,以及 socket 池最多 5 个 socket 连接,于是就把这两个给调大了,竟然有用,好的时候都能在 5s 内处理完,但还是发生了一两次超时的情况,微信报警都是 1W+ 的无返回。

目前看来大部分时候能处理完,说明 node 本身应该是能撑住这么多并发。但那一两次报警都有 1W+,显然也不正常,而那一两次报警时,接受的请求和数量都没什么不同,求教大家可能的情况?

大家如果有其他 node 性能优化或者高并发的建议,也欢迎讨论


17 回复

不懂 node ,不过为什么不用 nginx 或者其他成熟的软件


主要逻辑是转发消息,但还是稍稍有些判断的, node 帮助挡掉 TEMPLATESENDJOBFINISH 的消息,其他时候根据用户 groupid 转发给不同的后端

直接 return success 再用 setTimeout 或者队列转发到后端呀,后端根据需要用客服接口发送消息就可以。

对于 TEMPLATESENDJOBFINISH 是直接 return success 的,对于用户发来的消息,会根据情况转发给不同的后端,现在的问题是后端发送大量模板消息,微信回复的 TEMPLATESENDJOBFINISH 消息就都到 node 这来, node 有两次有 1W+ 的消息没在 5s 内处理完,感觉很诡异,要说扛不住,那应该每次都扛住了,但现在大部分时候扛住了就这么两次处理超时。。

那就再加大点 thread pool 和 max sockets 😁

加到多少呢。。现在是 4 核的机器, PM2 开了 4 个进程 64 个线程

socket pool 加到多大了?

7000 。。这个数字我看别人调几 W ,感觉机器比较一般就调了 7000 ,我也不知道调多少比较好

nodejs 最大的优点不是可以 scale up 用多台服务器均衡 request

用 DB 或其他的作一个队列

1 、调 v8 引擎参数;
2 、最大 socket 数在 0.12 版本之前默认是 5 ,之后都是正无穷,所以直接改成正无穷,或者升级版本;
3 、调系统限制参数,各种 limit ;
4 、开多个服务来扩展;
5 、运行时通过 v8-profiler ,查看内存和 CPU 状态,查出瓶颈;
6 、考虑上个消息队列。

收到消息记录到内存或文件立即返回,再用其他进程处理消息,在 node 前面加个 nginx ,分发到不同的 node 节点上。

最好的办法?当然是不用 node 。。。。。

同意 11L 。
如果没有特别实时性的要求,可以尝试 redis 等做 message queue

感觉应该直接压到队列里面啊。

我觉得是发生 fullGC 导致无法响应

针对Node.js在高并发下的性能优化,以下是一些专业建议:

  1. 异步非阻塞I/O

    Node.js的异步非阻塞特性使其在处理高并发时具有天然优势。通过异步I/O,Node.js可以在等待I/O操作(如数据库查询或文件读取)完成时继续处理其他请求。

    const http = require('http');
    const server = http.createServer((req, res) => {
      setTimeout(() => {
        res.writeHead(200);
        res.end('Hello World\n');
      }, 100);
    });
    server.listen(8000, () => {
      console.log('Server is running at http://localhost:8000/');
    });
    
  2. 使用Cluster模块

    利用Node.js的Cluster模块,可以充分利用多核CPU的处理能力,通过创建多个子进程(workers)来提高并发处理能力。

    const cluster = require('cluster');
    const http = require('http');
    const numCPUs = require('os').cpus().length;
    
    if (cluster.isMaster) {
      for (let i = 0; i < numCPUs; i++) {
        cluster.fork();
      }
    } else {
      http.createServer((req, res) => {
        res.writeHead(200);
        res.end('Hello World\n');
      }).listen(8000);
    }
    
  3. 优化代码和中间件

    尽量减少阻塞代码,避免全局变量,使用高效的数据结构。同时,在使用Express等框架时,应审查并减少中间件的使用,确保只加载必要的中间件。

  4. 使用缓存

    对于频繁访问的数据,可以使用内存缓存(如Node-cache)或分布式缓存(如Redis)来减少数据库访问次数。

  5. 监控与调优

    使用性能分析工具(如Node.js内置的profiler)和APM工具(如New Relic)来监控应用性能,并识别瓶颈进行调优。

回到顶部