情况: 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
请问哪位朋友有没有解决这类问题的经验?
|  |      1penjianfeng      2016-11-03 11:38:39 +08:00 关注下,公司一个系统准备换成 node 跑,有结果后希望分享下:-) | 
|  |      2tofishes OP @penjianfeng 好的,目前就这个并发问题了。 | 
|  |      3janxin      2016-11-03 11:47:49 +08:00 是不是只开了一个进程? | 
|  |      4mcfog      2016-11-03 11:49:27 +08:00 所以 8080 上是个无限牛逼的后端接口,然后 9190 上是你的问题的 node ,里面的逻辑是用 request 捅 8080 ,然后并发有问题? 没记错的话, request 库是带连接池的,默认并发只开了 5 ,所以你用并发 500 去压耗时很长是正常的 | 
|  |      6tofishes OP @mcfog  你理解反了, 8080 上是 node sever, 9190 是后端接口,并发 node 上一个地址,该地址又用了 request 去请求接口,统计了一下 request 开始到完成的耗时。 然后你说的 request 连接池是 'pool': { maxSockets: 5000 } ?改为 5000 也没有明显提升。 | 
|  |      7ibigbug      2016-11-03 12:47:40 +08:00 via iPhone 你看下系统 cpu 内存 和 load ? | 
|  |      9sherlocktheplant      2016-11-03 12:50:56 +08:00 看看是否是内存不足 发生内存换页 | 
|  |      10tofishes OP @xxxyyy 直接压后端耗时也很小的,所以是前端请求问题。 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 | 
|  |      11tofishes OP | 
|  |      12sherlocktheplant      2016-11-03 13:15:38 +08:00 @tofishes 发下转发的代码 | 
|  |      13powerfj      2016-11-03 13:16:27 +08:00 你这样测试很可能测试的是 request 请求的后端的接口的返回吧, 很可能是后面的接口不行了 | 
|  |      14sorra      2016-11-03 13:23:15 +08:00 把每个步骤的耗时都弄清楚一些。注意 console.log 也可能耗时。 网上宣传的高并发是高端服务器跑出来的,普通机器不要期望太高。 | 
|  |      15smallpath      2016-11-03 13:27:51 +08:00 先用 nginx 把请求转发到后端接口, 压一下看问题是不是 node 层的。 确定是 node 层的问题后,换一个请求库例如 superagent 跑一下,看看是不是所有库都有这个问题。 我们之前不是局域网时 ab 也是这样,但最后发现是本地带宽跑满了,解决后就没问题了 | 
|  |      16zhuangzhuang1988      2016-11-03 13:30:59 +08:00 用 visualstudio + node 扩展看下, 里面带有性能分析工具的 | 
|  |      17smallpath      2016-11-03 13:45:57 +08:00 superagent 跑起来还是有延迟的话,再换原生 http 模块试试,当然你有权限的话可以直接看后台接口的请求耗时对不对。 我觉得把 node 层请求用 nginx 转给后台可能有些效果 | 
|  |      18xxxyyy      2016-11-03 13:55:29 +08:00 via Android @tofishes 是不是你的 node 版本问题,我用 node.js 7.0 测你给出来的代码,每个请求的耗时相差不大(第一个与最后一个相差都不超过 80ms ) | 
|  |      19shanelau PRO 做排队啊。 关注下设备的性能,是什么原因找到的,网络还是 cpu 还是内存 | 
|  |      20tofishes OP @xxxyyy 我从 v6.9.1 升级到了 v7.0.0 ,耗时减少一半,但依然有超过 1000ms 的。 api 地址干脆使用了 http://localhost ,是本机 nginx 默认页面,耗时从 150ms ~ 500ms 左右都有。 | 
|  |      21enenaaa      2016-11-03 14:56:44 +08:00 不懂 node 。 考虑一下系统和网络性能,服务端 tcp 监听端口有接受队列, 频繁发起请求可能会有点耗时。 可以试一下在单个连接上测试 | 
|  |      22tofishes OP @sherlocktheplant 简单代码已附言 | 
|  |      23xxxyyy      2016-11-03 15:42:52 +08:00 @tofishes 你试下用以下的代码测下,如果结果差别不大,可能是后端的问题了: ``` const http = require("http"); const server = http.createServer((req, res) => { setTimeout(function () { res.writeHead(200); res.end(); }, Math.random() * 100); }); server.listen(8888); ``` ============================= 然后你上面贴出来的脚本也改成这样: ``` const request = require('request').defaults({ pool: { maxSockets: 5000 } }); const c = 500; const api = 'http://localhost:8888'; const costs = []; function doGet(i) { const start = Date.now(); const index = i; request.get(api, () => { const end = Date.now() - start; costs.push(`${index}: ${end}ms`); if (costs.length === c) { console.log(costs.join("\n")); } }); } for (let i = 0; i < c; i++) { doGet(i); } ``` | 
|  |      24wxx199101046      2016-11-03 15:50:42 +08:00 用上 pm2 结果会不会不一样? | 
|  |      25Arrowing      2016-11-03 16:26:14 +08:00 用利用多进程多核的特性没? 我用的 PM2 测的,服务器是 CPU:Intel(R) Xeon(R) 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 小时+ | 
|  |      27tofishes OP @xxxyyy 用了你的代码,用时变的比较均匀,截取最长耗时的和最短耗时,如下: ``` # 最短耗时: 127: 235ms 34: 285ms 62: 283ms 72: 283ms 97: 283ms 55: 289ms 89: 286ms 124: 283ms # 最长耗时: 279: 611ms 267: 612ms 437: 600ms 467: 599ms 421: 608ms 417: 609ms 436: 608ms 479: 606ms 461: 607ms 443: 608ms 448: 607ms 438: 609ms 430: 609ms ``` | 
|  |      28tofishes OP @wxx199101046 用 pm2 简单部署了下,结果还是一样 | 
|      29sampeng      2016-11-03 18:51:11 +08:00 为啥不把 node 换成 nginx 试试呢?直接 nginx 反向代理试试昂。。。 | 
|  |      30tofishes OP @sampeng 反向代理不是根本目的, node 做页面渲染的,转发接口这是其中一部分,不是 ningx 干的事儿。 | 
|  |      31hxsf      2016-11-03 20:02:28 +08:00 via iPhone mark  等下电脑回复 | 
|  |      32zhuangzhuang1988      2016-11-03 20:57:57 +08:00 | 
|  |      33xxxyyy      2016-11-03 21:05:50 +08:00 via Android @tofishes 这相差还是很大的,或许你可以用 wireshark 抓包,然后统计下时间,看能不能发现问题。 | 
|  |      34tofishes OP @zhuangzhuang1988 基于 Visual Studio ? osx 系统比较尴尬。。。我安装个虚拟机吧 | 
|      35sampeng      2016-11-04 10:52:04 +08:00 @tofishes nonono,问题是你需要确认是 node 的问题还是转发的问题。没问题就可以忽略掉 api 的故障了。。 我在使用 nodejs 的过程中转发发现也很诡异,经常堵得严严实实的。。。 | 
|  |      36tofishes OP @sampeng 是这样的,发起 1000 个请求,并发为 1 ,每次耗时都很低,但一旦并发数加大,加到 10 , 50 , 100 ,耗时就随之增加,可以认为是并发下的问题。 | 
|  |      37tofishes OP @zhuangzhuang1988 了解了一下, VS Code 有 mac 版本 | 
|  |      38zhuangzhuang1988      2016-11-04 11:28:25 +08:00 @tofishes vscode 没 profile 功能,记得 | 
|  |      39zhuangzhuang1988      2016-11-04 13:56:15 +08:00 而且 windows 上安装 nodejs 后支持这个   | 
|  |      41tofishes OP @wxx199101046 上次 pm2 用法错了,开双核后转发效率有提高了 | 
|  |      43scyuns      2016-11-10 03:09:39 +08:00 via Android 看不懂 尴尬 | 
|  |      44wxx199101046      2016-11-10 10:45:47 +08:00 @tofishes 那就好 理论上 pm2 多开就是提高并发啊 | 
|  |      45Sparetire      2016-11-21 17:21:29 +08:00 求教楼主最后解决了吗?我这里 4 核服务器 20W 请求,每个请求要压到 5s 以下。。不知道怎么优化 | 
|  |      46E2gCaBAT5I87sw1M      2019-06-14 11:23:16 +08:00 问题解决了: |