Nodejs 异步执行阻塞,strace发现堵在epoll_wait,求指点

Nodejs 异步执行阻塞,strace发现堵在epoll_wait,求指点

node新手,编译安装 ./configure --prefix=/path, 版本:v0.10.26

代码如下:

var http = require('http');
//http.globalAgent.maxSockets = 100;
for (var i = 0; i <= 500; i++)
{
    http.get("http://www.baidu.com", function(res){
            console.log('ok--\n');
    }).on('error', function(e){
            console.log(e);
    });
 }

执行效果:默认maxSockets是5,执行5个get后就会卡住。

strace 效果如下:

strace -p 25817 Process 25817 attached - interrupt to quit clock_gettime(CLOCK_MONOTONIC, {20601802, 628068955}) = 0 epoll_wait(5,

然后就阻塞在这里。 如果把maxSockets调大,执行指定数值后也会卡住。

请问是什么原因,是安装的不正确?


5 回复

Node.js 异步执行阻塞,strace 发现堵在 epoll_wait,求指点

问题背景

你是一个 Node.js 新手,使用 Node.js v0.10.26 版本。你在尝试通过 http.get 方法并发请求百度网站时,遇到了异步执行阻塞的问题。通过 strace 工具发现程序阻塞在 epoll_wait 函数上。

示例代码

var http = require('http');

for (var i = 0; i <= 500; i++) {
    http.get("http://www.baidu.com", function(res) {
        console.log('ok--\n');
    }).on('error', function(e) {
        console.log(e);
    });
}

问题分析

  1. 默认并发限制:Node.js 的 HTTP 客户端默认限制了同时进行的请求数量(默认为 5)。这是因为 Node.js 使用了一个全局的代理对象 http.globalAgent 来管理所有 HTTP 连接。

  2. epoll_wait 阻塞:当你的请求超过了默认的最大并发数(5),后续的请求会被挂起,等待之前请求完成。此时,Node.js 的事件循环会进入阻塞状态,等待 I/O 操作完成,这可以通过 strace 看到它在 epoll_wait 上阻塞。

解决方案

你可以通过调整 http.globalAgent.maxSockets 属性来增加并发连接的数量,从而避免阻塞问题。

var http = require('http');

// 设置最大并发连接数
http.globalAgent.maxSockets = 100;

for (var i = 0; i <= 500; i++) {
    http.get("http://www.baidu.com", function(res) {
        console.log('ok--\n');
    }).on('error', function(e) {
        console.log(e);
    });
}

注意事项

  • 性能与资源消耗:增加最大并发连接数可以解决当前问题,但需要注意可能会导致系统资源过度消耗,如文件描述符耗尽等。因此,在实际应用中需要根据实际情况合理设置。
  • 版本更新:Node.js 的最新版本已经改进了这些默认行为,并且提供了更高效的 I/O 处理机制。建议升级到最新的 LTS 版本以获得更好的性能和稳定性。

通过上述方法,你应该能够解决在高并发情况下遇到的阻塞问题。


var http = require('http');
//http.globalAgent.maxSockets = 100;
for (var i = 0; i <= 500; i++) {
  http.get("http://www.baidu.com", function(res) {
    res.on('data', function(chunk) {
      console.log('OK--\n');
    });
  }).on('error', function(e) {
    console.log(e);
  });
}

这样是ok的,http应该是开5个socket去做http请求而不是指的只发5个http请求

额 被你监视了 应该是 agent: null可以禁用agent

试了,ok。对其中的原理有点晕了。 为什么绑定on(‘data’, fun)就正常了呢?

这个问题的原因在于Node.js的HTTP客户端使用了全局代理http.globalAgent来管理并发连接,默认情况下最大并发连接数为5。当超过这个数量时,后续请求会被挂起等待之前的连接释放。

你的代码中同时发起了500个HTTP请求,但因为默认的最大并发连接数只有5,所以当这5个请求完成后,其他请求才会继续进行。这也是为什么你会看到程序会卡在epoll_wait上,因为它需要等待之前发起的连接完成。

你可以通过增加全局代理的最大连接数来解决这个问题:

http.globalAgent.maxSockets = 100; // 或者其他更大的值

示例代码如下:

var http = require('http');

http.globalAgent.maxSockets = 100; // 增加最大并发连接数

for (var i = 0; i <= 500; i++) {
    http.get("http://www.baidu.com", function(res) {
        console.log('ok--\n');
    }).on('error', function(e) {
        console.log(e);
    });
}

这样做之后,即使你一次性发起大量的请求,Node.js也能够更好地管理这些连接,并且不会出现卡在epoll_wait上的情况。

回到顶部