【问题标题】:Much slower response in node.js HTTP server with smaller files文件较小的 node.js HTTP 服务器的响应要慢得多
【发布时间】:2015-07-25 19:16:20
【问题描述】:

我正在 node.js 中为一个简单的 HTTP 服务器开发性能测试:

var http = require('http');
var fs = require('fs');

var NO_CACHE = true;
var fileCache;
var sendFile = function(conn, file) {
    conn.writeHead(200, {'Content-Type': 'text/html', 'Content-Length': file.length});
    conn.write(file);
    conn.end();
}
http.createServer(function (req, res) {
    if (NO_CACHE || fileCache == undefined) {
        fs.readFile('index.html', function(err, file) {
        fileCache = file;
        sendFile(res, fileCache);
        });
    } else {
        sendFile(res, fileCache);
    }
}).listen(8080, 'localhost');

(代码也可以在here找到)。

服务器总是读取文件“index.html”并返回它。我意识到如果文件大于或等于 65483 字节(非常接近 2^16 但不准确),服务器会在 1-3 毫秒内给出结果,如果文件较小,则持续 38-40 毫秒给出响应(可以找到正好 65483 字节的 index.html 文件here)。响应中的标头大约为 128 个字节:

Content-Type: text/html
Content-Length: 65483
Date: Thu, 14 May 2015 13:58:21 GMT
Connection: keep-alive

前两个标头由服务器设置,后两个由任何中间件自动设置。文件大小加上前两个头是 65533 字节,非常接近 65535 (2^16 - 1),差异可能是因为这两个头中的回车。

这种行为对我来说看起来很奇怪,因为更大的文件应该持续更长的时间被读取,而且时间差异非常大。

我使用 node.js 0.10.38 和 0.12.2 得到相同的结果。对于性能测试,我使用了 jMeter 2.13。

为了记录,在 jMeter 中使用具有相同文件和相同测试计划的 vert.x 不会发生这种行为(使用 vert.x 服务器,读取更大的文件需要更多时间)。

如果有人知道原因可能是什么(以及如何避免小文件的原因),我很想知道。

【问题讨论】:

  • 你能转储大/小文件的响应头吗?另外,如果你使用 vert.x,你可能有兴趣看看我的bayou server
  • 我更新了问题。服务器有意设置了两个标头,并自动设置了另外两个标头。服务器“块”非常接近 64KB...
  • 小文件的响应头相同(Content-Length 除外)?我的第一直觉是 TCP NODELAY 选项,如果不设置,这对于小数据包来说是可怕的。但它应该默认为nodejs设置所以它可能不是原因。
  • 缓存会导致问题吗?大文件被缓存,小文件不被缓存? (客户端或服务器端)
  • @coyotte508 - 即使没有任何缓存,它也不会那么慢(30 req/s)。中间有人正在缓冲并持有小数据包。

标签: node.js performance http


【解决方案1】:

正如bayou.io 所指出的,该行为是由TCP noDelay 引起的。我添加到服务器:

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

它会在 1-3 毫秒内按预期给出响应。

【讨论】:

  • 取而代之的是 req.socket.setNoDelay(true);可以在 requestListener 中使用。
  • 默认不设置?那会烧死很多人。那个 Nagle 家伙浪费了很多人的时间。
  • Node.js 文档只说 noDelay 对于套接字 (nodejs.org/api/net.html#net_socket_setnodelay_nodelay) 默认为 true。对于 HTTP 请求,它没有被告知 (nodejs.org/api/http.html#http_request_setnodelay_nodelay),但我的测试和 Internet 上的其他来源确认它默认设置为 false(默认情况下,Nagle 算法在 HTTP 请求中启用)。到目前为止,Nagle 还在我所有的 HTTP 服务器上浪费了很多时间:(
  • 我认为文档意味着true 是方法参数的默认值 - 没有参数的setNoDelay()setNoDelay(true) 相同。该选项的默认值仍然是false
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-01-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-11-10
相关资源
最近更新 更多