【问题标题】:Thousands of concurrent http requests in node节点中的数千个并发http请求
【发布时间】:2015-02-08 15:18:22
【问题描述】:

我有一个包含数千个 URL 的列表。我想通过 http 请求进行健康检查 (healt.php)。

这是我的问题:

我在 node.js 中编写了一个应用程序。它以汇集的方式发出请求。我使用一个变量来控制我打开多少并发连接。 300,即。 一个一个,每个请求都那么快,不超过500ms。

但是当我运行应用程序时,结果是:

$ node agent.js

200ms   url1.tld
250ms   url4.tld
400ms   url2.tld
530ms   url8.tld
800ms   url3.tld
...
2300ms  urlN.tld
...
30120ms urlM.tld

似乎并发有限制。当我执行时

$ ps axo nlwp,cmd | grep node

结果是:

6 node agent.js

有 6 个线程来管理所有并发连接。我在节点中找到了一个 evn 变量来控制并发:UV_THREADPOOL_SIZE

$ UV_THREADPOOL_SIZE=300 node agent.js

200ms   url1.tld
210ms   url4.tld
220ms   url2.tld
240ms   url8.tld
400ms   url3.tld
...
800ms  urlN.tld
...
1010ms urlM.tld

问题仍然存在,但结果要好得多。使用 ps 命令:

$ ps axo nlwp,cmd | grep node

132 node agent.js

下一步:查看node的源码,发现deps/uv/src/unix/threadpool.c中有一个常量:

#define MAX_THREADPOOL_SIZE 128

好的。我已将该值更改为 2048,编译并安装节点并运行一次命令

$ UV_THREADPOOL_SIZE=300 node agent.js

一切似乎都很好。响应时间不会逐渐增加。但是当我尝试使用更大的并发数时,就会出现问题。但是这次和线程数无关,因为用ps命令我看到线程已经够多了。

我尝试在 golang 中编写相同的应用程序,但结果是一样的。时间逐渐增加。

所以,我的问题是:并发限制在哪里?内存和 cpu 负载和带宽没有超出范围。我调整了 sysctl.conf 和 limits.conf 以避免一些限制(文件、端口、内存……)。

【问题讨论】:

  • 虽然不是答案,但您可以考虑使用 cluster 模块来利用所有可用的 CPU,以便将工作更好地分布在您的硬件上。上下文切换也可能在这里发挥作用,尽管我认为它不会导致如此严重的延迟。

标签: linux node.js concurrency


【解决方案1】:

您可能会被 http.globalAgent 的maxSockets 限制。根据您使用的是 http 还是 https,看看这是否能解决您的问题:

require('http').globalAgent.maxSockets = Infinity;
require('https').globalAgent.maxSockets = Infinity;

【讨论】:

    【解决方案2】:

    如果您使用requestrequest-promise,您可以设置池大小:

      request({
        url: url,
        json: true,
        pool: {maxSockets: Infinity},
        timeout: 2000
      })
    

    更多信息在这里:https://github.com/request/request

    【讨论】:

      猜你喜欢
      • 2018-07-12
      • 1970-01-01
      • 1970-01-01
      • 2023-01-12
      • 1970-01-01
      • 2016-03-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多