Nodejs 线上项目并发问题,深夜在线求救
Nodejs 线上项目并发问题,深夜在线求救
环境 v14.x 框架 nestjs7 devops:k8s+docker
问题:并发不多的情况下 rt 高 复现:写一个接口不做任何操作直接返回,内网 1000 并发都要 2s 了,2000 并发的情况下,50%的接口 rt 就超过 10s 了。在这种情况出现的时候去容器内部 curl localhost 也会出现卡顿。通过增加 pod 并不能改善这个情况,感觉 4c8g 规格的一个实例和 10 个实例压测下来负载是一样的并没有增加。
所以,是我的写法有问题吗?如果不是有可能是 k8s 环境配置吗?跪求,要死了。
横向扩展不能增加吞吐先观察一下流量是否正确分发了,其次考虑是否有全局单点,比如缓存和数据库等。以上都没问题那就本地开发环境开 profiling 观察热点和瓶颈。
测试接口未访问任何服务,直接返回 null ,感觉是吞吐量不够。
开发环境复现不了问题
LB 是不是有问题
前端负载均衡是啥 是不是那里就挂了
系统负载情况呢?试试不用 docker 或者用 network host ?
容器内也对 localhost 跑下压测,先诊断 pod 内部有没有问题。若吞吐量符合正向预期再向前排查链路,网关,lb ,带宽等
按照之前都历史经验,这个是 Linux 服务上,TCP 相关的参数没有调整。因为这个参数有限制,所以并发低都时候 RT 也不高( 1000 的并发),并发高( 2000 并发)的时候 RT 和 成功率够不高。
你按照这两个帖子的思路处理这个 RT 和成功率就会上来了:
[1] https://cloud.tencent.com/developer/article/1521303
[2] https://netkiller.sourceforge.net/testing/performance/stress.html
(这两个链接是我按照关键字搜索的,你照着参考,把你的机器参数改大就行了)
具体的原理上,你参考一下这个文章[1]。十有八九的类似的性能问题都是出现在这里的。
[1] https://www.cnblogs.com/wx170119/p/12068005.html
一楼说的挺对的,链路追踪一下看到底从哪到哪了,怀疑并没有正确分发
看起来像是请求的服务器端使用了阻塞式处理,不过我不了解 nestjs 。lz 试一下在 k8s 搭一个 nginx 的 lb 服务,看看能不能处理 1w 以上的并发,如果可以,说明你的 service 配置不对,如果不行,那就是 k8s 有问题了。
你在容器内都卡顿,看上去不像 k8s 的锅(也许是 pod 设置限制了 cpu ),单拉出来一台低配物理机调试吧
楼主解决了吗,快来总结一下
上面都在说啥, 一个空方法返回都会 10s , 还上链路追踪,还加缓存,背八股文也得看实际场景呀, 猜测线程池的问题,不懂 nestjs7 , 但是猜测类似于 tomcat 的线程池, 楼主用的默认配置
不了解你的那个,你写一个 go server 丢上去,看看并发能到多少
我之前遇到一个问题就是 nginx 的连接没有保持,keepalive_timeout
nestjs 非 io 操作只有一个线程在处理, 你开多大机器规格他都只有一个线程在干活.
你看看 cpu 占用, 如果有一个核心占用一直在 80%以上, 那不用想了, 就是 cpu 忙不过来了.
1000 并发, rt 要 2s, 这时候多少个 pod, 如果按负载是正常的情况看, 平均下去每个 pod 是多少请求. 按你 2000 并发看, 2000/10 个 pod,每个 pod 是 200, 大概率是 nestjs 的线程问题. Tomcat 默认线程也就 200. 负载情况可以通过 k8s 看流量或者自己加加日志统计.
对方运维不配合,没办法排查。
升级了下 fastify 能抗到 2000 多 TPS ,后续流量也变小了就没管了
难过,当场失去绝佳提高自身经验的机会
遇到Node.js线上项目的并发问题,通常涉及到事件循环、异步I/O处理、以及可能的资源瓶颈。以下是一些常见的排查和优化策略:
-
检查Event Loop延迟: 使用
process.nextTick
或setImmediate
的回调来监控事件循环的延迟。如果延迟较大,可能是有阻塞操作或未优化的异步代码。setInterval(() => { const start = Date.now(); setImmediate(() => { console.log(`Event Loop Delay: ${Date.now() - start}ms`); }); }, 1000);
-
优化异步I/O: 确保数据库查询、文件读写等操作都使用了异步方法,并且合理使用了连接池。
-
使用Cluster模块: Node.js的Cluster模块可以充分利用多核CPU,通过创建多个子进程来分摊负载。
const cluster = require('cluster'); const numCPUs = require('os').cpus().length; if (cluster.isMaster) { console.log(`Master ${process.pid} is running`); for (let i = 0; i < numCPUs; i++) { cluster.fork(); } cluster.on('exit', (worker, code, signal) => { console.log(`worker ${worker.process.pid} died`); }); } else { // Worker can share any TCP connection // In this case it is an HTTP server require('./app.js'); }
-
监控和日志: 使用监控工具(如PM2)和详细的日志记录,可以帮助你快速定位问题。
如果以上方法仍未解决问题,建议深入分析具体业务逻辑和代码,查找潜在的阻塞点或资源泄露。