情况: 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
请问哪位朋友有没有解决这类问题的经验? +++++++++++++++++ 2016-11-03 13:00:06 补充一下,简单测试问题的代码,序号输出是无序的,说明是异步,只不过越到后面越耗时:
const request = require('request').defaults({
pool: { maxSockets: 5000 }
});
const c = 500;
const api = '替换为一个api';
function doGet(i) {
const start = Date.now();
const index = i;
request.get(api, () => {
const end = Date.now() - start;
console.log(`${index}: ${end}ms`);
});
}
for (let i = 0; i < c; i++) {
doGet(i);
}
执行结果:
3: 570ms
1: 582ms
5: 580ms
7: 580ms
9: 580ms
11: 580ms
2: 582ms
0: 591ms
4: 582ms
6: 582ms
12: 582ms
10: 582ms
8: 583ms
14: 583ms
13: 583ms
16: 583ms
17: 584ms
20: 583ms
22: 583ms
24: 583ms
26: 583ms
28: 582ms
30: 582ms
...
457: 2262ms
467: 2263ms
469: 2263ms
237: 2283ms
474: 2267ms
471: 2267ms
493: 2269ms
475: 2272ms
479: 2271ms
477: 2272ms
485: 2272ms
483: 2273ms
481: 2273ms
487: 2273ms
489: 2274ms
495: 2273ms
497: 2273ms
499: 2274ms
491: 4380ms
关注
ip相同?端口被打满了 做个池限制下并发数 或者 相同请求做cache 或者 加机器
我推荐,把“响应计时”的功能放在server代码里,即,
- server接收到请求 — 开始计时。
- server端res.end()之前 — 停止计时,并计算流逝的时间。 这样能够更客观地绕开网络延时 与 操作系统层 造成的意外 影响。我这边的项目,在前端与后端都是 响应时间的审计 功能。
@robbenmu 本机请求另外一台服务器,单独压测服务器接口是很快的,然后本机通过request请求接口(连接池已开到5000),循环500次,相当于同时发起500次请求,就会增大耗时,是node方的问题。
@stuartZhang 不是统计server接口响应时间,是统计node转发接口耗时。单独server接口耗时是很小的,一般在30ms以下。
@tofishes node转发接口 是什么意思?你是说:node背后还有其它的后端server。并且,那个在node背后的server响应时间很短,但是,加上node之后,整体的响应时间就很长了吗?
如果是那样的话,在nodejs的代码里有计算密集型的代码吗?
推荐你跟踪一下内存使用量。如果内存消耗猛涨的话,对nodejs的性能一定会有很大的负影响的。
ab这么多并发直接到api,时间或不会变长?
@JasonBoy 现在是变的太长,太耗时
@stuartZhang node背后还有其它的后端server。并且,那个在node背后的server响应时间很短,但是,加上node之后,整体的响应时间就很长了。 你理解的没错。没有计算密集,内存也不高,仅仅是并发请求而已。
@tofishes 你的运行操作系统是CentOS, Ubuntu, Mac OS还是Windows呀? node与后端的server之间使用的什么通信协议呀? 我推荐,你在nodejs端的程序里加时间日志,然后再分析。或许一个更详细的包括如下字段的时间日志会更有帮助:
- node接收 客户端请求 至 返回结果 的 时长。
- node等待 更后端server的响应 的 时长
最后再对比ab压测客户端的时间统计。咱们再分析。
先单独测试Node性能,再集成,很可能是中间环节问题吧
@DevinXian 程序实在是太简单,基本没有中间环节,唯一的中间环节就是发接口请求了
@stuartZhang 程序实在是很简单,没有复杂的地方,你说的这些暂时用不到。
node里面有dns问题,你检查一下,跟这个有关系吗?
From Noder
@qimenxiaozi 请大侠进一步解释一下好吗?nodejs在什么环节做dns处理。
如果是因为dns的问题的话,直接请求ip地址大约就能解决吧?
你的网络上行是无限大的? 你浏览器打开一个网页很快,但是你同时打开 100 个试试?
@stuartZhang 默认开启四个线程处理文件和dns,如果四个thread都被占用,就会导致socket 积压,后面的请求只能等前面的释放资源,所以请求就会慢慢的拖慢,但是你的code也没有看,只能做排除法,找一个trace的工具,检查一下请求spend的时间分布,在来看看是为什么? From Noder
单个实例性能肯定是有限的,和语言没关系。限制单个实例流量,通过起多个实例增大并发量
楼主,这个问题解决了没?有什么解决问题的经验 可以 分享 吗?
mark