Nodejs 请求接口在高并发下耗时很大,而单个请求非常快
Nodejs 请求接口在高并发下耗时很大,而单个请求非常快
情况: request.js 库请求接口, express.js 做 server ,实现了 curl http://localhost:8080/proxy-api 本地一个地址,在 router 里用 request.js 请求接口,统计了一下请求耗时,单个请求耗时很低,如下:
get http://ip:9190/user/getUserInfo 13 ms
然后分别使用 webbench 和 ab 做并发测试,并发 500 ,发现接口有非常大的耗时。
# 测试命令
ab -n 1000 -c 200 -r http://localhost:8080/proxy-api
webbench -t 10 -c 500 http://localhost:8080/proxy-api
# 截取部分响应耗时:
get http://ip:9190/user/getUserInfo 2019 ms
cost time: 2020
get http://ip:9190/user/getUserInfo 2062 ms
cost time: 2062
get http://ip:9190/user/getUserInfo 2064 ms
cost time: 2065
get http://ip:9190/user/getUserInfo 2063 ms
cost time: 2063
get http://ip:9190/user/getUserInfo 2062 ms
cost time: 2063
get http://ip:9190/user/getUserInfo 2063 ms
cost time: 2063
get http://ip:9190/user/getUserInfo 2061 ms
cost time: 2062
get http://ip:9190/user/getUserInfo 2063 ms
cost time: 2064
get http://ip:9190/user/getUserInfo 2063 ms
...
...
get http://ip:9190/user/getUserInfo 1362 ms
cost time: 1362
get http://ip:9190/user/getUserInfo 1361 ms
cost time: 1362
get http://ip:9190/user/getUserInfo 1362 ms
cost time: 1362
get http://ip:9190/user/getUserInfo 1362 ms
cost time: 1362
get http://ip:9190/user/getUserInfo 1362 ms
cost time: 1362
get http://ip:9190/user/getUserInfo 1363 ms
cost time: 1363
get http://ip:9190/user/getUserInfo 1362 ms
cost time: 1362
...
...
get http://ip:9190/user/getUserInfo 1006 ms
cost time: 1006
get http://ip:9190/user/getUserInfo 627 ms
cost time: 628
get http://ip:9190/user/getUserInfo 629 ms
cost time: 629
get http://ip:9190/user/getUserInfo 628 ms
cost time: 629
get http://ip:9190/user/getUserInfo 1403 ms
cost time: 1403
get http://ip:9190/user/getUserInfo 1402 ms
请问哪位朋友有没有解决这类问题的经验?
关注下,公司一个系统准备换成 node 跑,有结果后希望分享下:-)
好的,目前就这个并发问题了。
是不是只开了一个进程?
所以 8080 上是个无限牛逼的后端接口,然后 9190 上是你的问题的 node ,里面的逻辑是用 request 捅 8080 ,然后并发有问题?
没记错的话, request 库是带连接池的,默认并发只开了 5 ,所以你用并发 500 去压耗时很长是正常的
没有做任何进程操作,默认的简单程序
你理解反了, 8080 上是 node sever, 9190 是后端接口,并发 node 上一个地址,该地址又用了 request 去请求接口,统计了一下 request 开始到完成的耗时。 然后你说的 request 连接池是 ‘pool’: { maxSockets: 5000 } ?改为 5000 也没有明显提升。
你看下系统 cpu 内存 和 load ?
你直接压后端的接口的耗时是多少?
看看是否是内存不足 发生内存换页
直接压后端耗时也很小的,所以是前端请求问题。
ab 压前端转发:
Requests per second: 171.05 [#/sec] (mean)
Time per request: 1169.261 [ms] (mean)
Time per request: 5.846 [ms] (mean, across all concurrent requests)
Transfer rate: 1981.31 [Kbytes/sec] received
ab 直接压后端接口:
Requests per second: 858.12 [#/sec] (mean)
Time per request: 233.068 [ms] (mean)
Time per request: 1.165 [ms] (mean, across all concurrent requests)
Transfer rate: 190.23 [Kbytes/sec] received
我都是在本地测试,只有后端接口是局域网内一个服务器, mac pro 13 中配,应该不是你们所说的问题
发下转发的代码
你这样测试很可能测试的是 request 请求的后端的接口的返回吧, 很可能是后面的接口不行了
把每个步骤的耗时都弄清楚一些。注意 console.log 也可能耗时。
网上宣传的高并发是高端服务器跑出来的,普通机器不要期望太高。
先用 nginx 把请求转发到后端接口, 压一下看问题是不是 node 层的。
确定是 node 层的问题后,换一个请求库例如 superagent 跑一下,看看是不是所有库都有这个问题。
我们之前不是局域网时 ab 也是这样,但最后发现是本地带宽跑满了,解决后就没问题了
用 visualstudio + node 扩展看下, 里面带有性能分析工具的
superagent 跑起来还是有延迟的话,再换原生 http 模块试试,当然你有权限的话可以直接看后台接口的请求耗时对不对。
我觉得把 node 层请求用 nginx 转给后台可能有些效果
是不是你的 node 版本问题,我用 node.js 7.0 测你给出来的代码,每个请求的耗时相差不大(第一个与最后一个相差都不超过 80ms )
做排队啊。
关注下设备的性能,是什么原因找到的,网络还是 cpu 还是内存
我从 v6.9.1 升级到了 v7.0.0 ,耗时减少一半,但依然有超过 1000ms 的。 api 地址干脆使用了 http://localhost ,是本机 nginx 默认页面,耗时从 150ms ~ 500ms 左右都有。
不懂 node 。
考虑一下系统和网络性能,服务端 tcp 监听端口有接受队列, 频繁发起请求可能会有点耗时。
可以试一下在单个连接上测试
简单代码已附言
你试下用以下的代码测下,如果结果差别不大,可能是后端的问题了:<br>const http = require("http");<br><br>const server = http.createServer((req, res) => {<br> setTimeout(function () {<br> res.writeHead(200);<br> res.end();<br> }, Math.random() * 100);<br>});<br><br>server.listen(8888);<br>
=============================
然后你上面贴出来的脚本也改成这样:<br>const request = require('request').defaults({<br> pool: { maxSockets: 5000 }<br>});<br><br>const c = 500;<br>const api = 'http://localhost:8888';<br><br>const costs = [];<br>function doGet(i) {<br> const start = Date.now();<br> const index = i;<br> request.get(api, () => {<br> const end = Date.now() - start;<br> costs.push(`${index}: ${end}ms`);<br> if (costs.length === c) {<br> console.log(costs.join("\n"));<br> }<br> });<br>}<br><br>for (let i = 0; i < c; i++) {<br> doGet(i);<br>}<br>
用利用多进程多核的特性没?
我用的 PM2 测的,服务器是 CPU:Intel® Xeon® E5-2640 0 @ 2.50GHz 共 24 核 MEM:32G
并发数 TPS 响应时间 CPU 成功数 写文件 丢失率 时间
5000 10331.5 0.446 55% 19327244 19323366 0.02% 1 小时
10000 10392.1 0.86 55% 23631728 23626987 0.02% 1 小时
2000 9673.45 0.198 55% 416065314 415983941 0.0195% 11 小时+
没有实用多核多进程
用了你的代码,用时变的比较均匀,截取最长耗时的和最短耗时,如下:<br># 最短耗时:<br>127: 235ms<br>34: 285ms<br>62: 283ms<br>72: 283ms<br>97: 283ms<br>55: 289ms<br>89: 286ms<br>124: 283ms<br><br># 最长耗时:<br>279: 611ms<br>267: 612ms<br>437: 600ms<br>467: 599ms<br>421: 608ms<br>417: 609ms<br>436: 608ms<br>479: 606ms<br>461: 607ms<br>443: 608ms<br>448: 607ms<br>438: 609ms<br>430: 609ms<br>
用 pm2 简单部署了下,结果还是一样
为啥不把 node 换成 nginx 试试呢?直接 nginx 反向代理试试昂。。。
反向代理不是根本目的, node 做页面渲染的,转发接口这是其中一部分,不是 ningx 干的事儿。
mark 等下电脑回复
这相差还是很大的,或许你可以用 wireshark 抓包,然后统计下时间,看能不能发现问题。
基于 Visual Studio ? osx 系统比较尴尬。。。我安装个虚拟机吧
nonono,问题是你需要确认是 node 的问题还是转发的问题。没问题就可以忽略掉 api 的故障了。。
我在使用 nodejs 的过程中转发发现也很诡异,经常堵得严严实实的。。。
是这样的,发起 1000 个请求,并发为 1 ,每次耗时都很低,但一旦并发数加大,加到 10 , 50 , 100 ,耗时就随之增加,可以认为是并发下的问题。
了解了一下, VS Code 有 mac 版本
vscode 没 profile 功能,记得
而且 windows 上安装 nodejs 后支持这个
服务器 24 核,性能不要太好。想问下,你用的测试软件是什么?
上次 pm2 用法错了,开双核后转发效率有提高了
我司测试大神测的,软件名是 loadrunner
看不懂 尴尬
那就好 理论上 pm2 多开就是提高并发啊
求教楼主最后解决了吗?我这里 4 核服务器 20W 请求,每个请求要压到 5s 以下。。不知道怎么优化
问题解决了:![123]( https://imgchr.com/i/V4sQl4 ‘‘123’’)