【问题标题】:node http server 4 x FASTER when keep-alive disabled?禁用保持活动时节点http服务器快4倍?
【发布时间】:2016-06-20 08:28:25
【问题描述】:

Keep-alive 应该加快网站的速度。

但是,当我在 chrome (localhost:8080) 中运行这个死的简单服务器时,我得到了这些加载时间:

  • 大约 100 毫秒,带有 "Connection: close" 标头(即未注释 setHeader 行)

  • 大约 400 毫秒,启用标准保持活动状态

我做错了什么?谁能重现我的结果?

过去 2 天我一直在为此头疼。

var fs = require('fs')
// preparing 50 2k files ...
var a = [], txt = '/*\n' + 'x'.repeat(2000) + '\n*/'
for (var i = 0; i < 50; i++) {
  var name = '/test' + i + '.js'
  fs.writeFile(__dirname + name, txt)
  a.push('<script src="' + name + '"></script>')
}
fs.writeFile(__dirname + '/index.html', a.join('\n') + '\nhello world')

var serve = function (req, res) {
  if (req.url === '/favicon.ico') {
    res.statusCode = 404; return res.end()
  }
  var pth = req.url + (req.url.match(/\/$/) ? 'index.html' : '')
  var s = fs.createReadStream(__dirname + pth)
  res.on('finish', function () { console.log('done', req.url) })
  // THIS IS THE KILLER LINE. Just uncomment and restart the server.
  // on my system, the page loads 4 times FASTER
  // res.setHeader('Connection', 'close')
  res.statusCode = 200; s.pipe(res)
}
require('http').createServer(serve).listen(8080)

编辑

为清楚起见,使用标准快速服务器时的行为是相同的。以下服务器代码将产生相同的结果(至少在我的系统上)

// express server code
var express = require('express')
var app = express()
var closeConnection = function (req, res, next) {
  res.setHeader('Connection', 'close'); next()
}
// THIS IS THE KILLER LINE. Just uncomment and restart the server.
// on my system, the page loads 4 times FASTER
// app.use('*', closeConnection)
app.use(express.static(__dirname))
require('http').createServer(app).listen(8080)

【问题讨论】:

  • 不是因为缺少Content-Length header吗? IE。浏览器不知道响应何时结束,所以这 400 毫秒是人为的,即它包括等待时间?与Connection: close 不同,浏览器知道响应何时结束。那将是我的盲目射击。
  • 不,我不这么认为。该行为与标准 Express 服务器完全相同,您提到的问题不存在。你能重现这个问题吗?

标签: node.js http server keep-alive


【解决方案1】:

您的服务器中发生的事情与互联网上发生的事情之间存在巨大差异,尽管我对您在此处报告的指标感到有些惊讶。您没有说明如何获取指标或内容生成时间。我们可以假设后者低于 100 毫秒,这表明您的环回接口上发生了一些非常奇怪的事情,或者 node.js 在这种情况下正在做一些非常奇怪的事情,或者可能是浏览器任务的调度阻塞了网络服务器任务。

当然,如果您发布的页面需要渲染多个文件,并且正在通过 Internet 传递数据,禁用 keepalive 应该会降低您的服务器负载和 CPU 使用率,但会增加页面加载时间。

我建议您开始添加其他组件,看看何时恢复预期的状态。我会先在单独的机器上运行客户端/运行多个客户端。

【讨论】:

  • 感谢您的回答。我报告的加载时间只是来自通常的 Chrome 开发者工具 -> 网络。从你说的我明白你无法重现这个问题,所以我的机器肯定有问题。当我找到一个时,我会尝试在另一个上运行代码,并报告结果。谢谢。
  • 我没有用 node.js / chrome 测试过这个。我已经用 Apache (prefork) 和 Firefox 对它进行了测试,我发现客户端连接关闭/kaeepalive 的响应时间没有差异。
  • 谢谢@symcbeam。 Chrome 与 Firefox 应该没什么区别。我已经测试了从内部网络上的不同设备和 Firefox 进行的访问,以排除浏览器和服务器争夺 CPU 的可能性:页面加载时间仍然是启用保活的两倍左右。我应该提一下,当我的服务器落后于 Nginx 时,差异也消失了,因为 Nginx 关闭了与后端服务器的连接。可能是 Apache 做同样的事情??
【解决方案2】:

这似乎是由于Nagle's algorithmactive by default。这会在发送 TCP 数据包之前造成延迟,等待可能在一个数据包中发送更多数据以避免数据包太小。

因为关闭连接会导致挂起的数据包立即发送,所以这不会影响不使用 keep-alive 连接时的延迟。

正如this answer 中所述,Nagle 的算法可以这样禁用:

server.on("connection", function (socket) {
    socket.setNoDelay(true);
});

这应该可以解决延迟问题。请注意,如果您不自己处理缓冲并发送大量小数据包,它可能会降低传输速率。

我注意到当通过管道传输响应时会出现问题(导致使用分块传输编码)(甚至使用 Content-Length 标头),但在使用 res.json() 一次发送完整响应时不会出现问题。

此外,自 Node.js 8.0.0 以来,此问题似乎少得多。不过,在我的情况下,禁用 Nagle 的算法仍然有积极的影响。

【讨论】:

    猜你喜欢
    • 2018-03-18
    • 1970-01-01
    • 2020-02-02
    • 2012-12-24
    • 1970-01-01
    • 1970-01-01
    • 2020-04-09
    • 1970-01-01
    • 2013-03-18
    相关资源
    最近更新 更多