nodejs 请求接口在高并发下耗时很大,而单个请求非常快
发布于 2 个月前 作者 tofishes 1006 次浏览 来自 问答

情况: 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
20 回复

ip相同?端口被打满了 做个池限制下并发数 或者 相同请求做cache 或者 加机器

我推荐,把“响应计时”的功能放在server代码里,即,

  1. server接收到请求 — 开始计时。
  2. 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端的程序里加时间日志,然后再分析。或许一个更详细的包括如下字段的时间日志会更有帮助:

  1. node接收 客户端请求 至 返回结果 的 时长。
  2. 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

单个实例性能肯定是有限的,和语言没关系。限制单个实例流量,通过起多个实例增大并发量

楼主,这个问题解决了没?有什么解决问题的经验 可以 分享 吗?

回到顶部