首页 > 解决方案 > Node.js http 请求导致 CLOSE_WAIT

问题描述

我创建了一个 JavaScript 程序,它检查网络上各种设备的状态,并将它们的状态报告给 MQTT 服务器,以便与我的家庭自动化仪表板集成。为了检查设备状态,我打开了一个连接(HTTP、HTTPS 或通用 TCP)。如果连接成功,设备会报告为 up。如果失败或超时,则报告为停机。然后我结束连接。

这运行良好,除了当我连接到我的互联网路由器的 HTTP 管理界面时。使用路由器,连接卡在 CLOSE_WAIT 中。

netstat -t
tcp    24160      0 uno.home:52544          router.0.168.192.i:http CLOSE_WAIT
tcp    24160      0 uno.home:49742          router.0.168.192.i:http CLOSE_WAIT
tcp    24160      0 uno.home:50820          router.0.168.192.i:http CLOSE_WAIT
tcp    24160      0 uno.home:48084          router.0.168.192.i:http CLOSE_WAIT
...

这将一直持续到我关闭程序或内核不再能够分配 TCP 内存。

我正在对 Nginx Web 服务器和 Portainer(基于 Web 的容器管理器)运行相同的检查。这些都不会导致相同的 CLOSE_WAIT 问题。我怀疑是路由器出了问题,但我想知道我的代码中是否有任何可以帮助缓解问题的地方。

这是执行 HTTP 检查的函数:

/**
 * Connect to an HTTP server and report the result.
 * @param {string} name  A friendly name given to the service check.
 * @param {string} host  The server's hostname or IP address.
 * @param {number} port  The TCP port number the server listens on.
 * @param {string} path  The directory and file name portion of the URL (e.g. /index.html)
 */
function httpCheck(name, host, port, path) {
  const httpRequest = http.get(`http://${host}:${port}${path}`, (response) => {
    if (debug)
      console.log(`HTTP check for http://${host}:${port}${path} returned: ${response.statusCode}`);
    if (response.statusCode < 400)
      publishStatus(name, config.statusMsg.success);
    else
      publishStatus(name, config.statusMsg.failure);
  });
  httpRequest.on('data', (chunk) => {
    let data = chunk;  // Read and throw away.
  });
  httpRequest.on('close', () => {
    httpRequest.end();
  });
  httpRequest.on('error', (err) => {
    publishStatus(name, config.statusMsg.failure);
    httpRequest.end();
  });
}

httpRequest.end()可能是多余的。我添加了这些以尝试解决此问题。我还添加了这样的.on('data')想法,路由器的 Web 服务器可能会等待我在它认为完整之前阅读整个页面。

我还简要地考虑过只做一个 HEAD 请求,但路由器给出了一个“501:方法未实现”错误。

同样,我觉得奇怪的是,我对 Nginx 和 Portainer 的检查在这段代码中运行良好。但是,也许我缺少一些东西。是否有可能改进代码以避免TIME_WAIT?

标签: node.jshttprequesttime-wait

解决方案


推荐阅读