NodeJS的高延迟

时间:2013-06-22 02:56:16

标签: javascript node.js express socket.io nodejitsu

此问题特别适用于Nodejitsu,但类似的效果似乎发生在其他VPS上。我有一个使用socket.io的实时游戏,我注意到的一件事是偶尔服务器会在响应之前等待过多的时间。如果在该时间范围内发送了多个请求,则它们的行为就像它们已经排队并立即处理一样。我怀疑它与硬件共享上的其他用户的存在有着模糊的关联(就像任何VPS一样)。

无论如何,为了测试它(并确保它不是由于我的游戏代码),我构建了一个最小的测试用例:

express = require('express')
http = require('http')

app = express()
server = http.Server(app)

io = require('socket.io').listen(server)

io.sockets.on('connection', function(sock){
    sock.on('perf', function(data, cb){
        cb([Date.now()]); //respond with the current time
    })
})

app.get('/', function(req, res){
    res.header("Access-Control-Allow-Origin", "*")
    res.header("Access-Control-Allow-Methods", "HEAD,GET,PUT,POST,DELETE")
    res.header("Access-Control-Allow-Headers", "X-Requested-With")

    res.end(JSON.stringify([Date.now().toString()])); //http equivalent of perf function
})

server.listen(process.env.PORT || 6655, function(){
    console.log('listening now')
})

我有一个简单的空白HTML页面,其中包含socket.io,它会定期发送perf事件,并计算回调触发所需的时间。它仍然显示同样的事情:

graph showing lag spike

请注意,条形长度表示时间量的平方根,而不是线性数量。

当我没有依赖socket.io时,我使用XHR对当前响应时间进行类似的测量,结果非常相似,很多低延迟响应(尽管基线比websockets高,如预期的那样)还有一些偶然的尖峰似乎堆积起来。

奇怪的是,如果你在多个浏览器窗口和不同的浏览器中打开它,不同的浏览器之间似乎存在相关性(并且它在某些服务器上完全不存在或显着不那么频繁)这似乎是意味着它是服务器端的现象。但是,某些浏览器会出现延迟峰值而其他浏览器不会出现延迟峰值,并且同一会话中的两个Chrome窗口看起来几乎完全相同,这表明它是本地发生的(每台计算机或每个浏览器,网络)明智的)。

从左到右:Chrome隐身,Chrome(常规),Firefox,Chrome(常规)

charts on four windows

无论如何,这让我困惑了几个月,我真的很想了解是什么导致它以及如何解决它。

3 个答案:

答案 0 :(得分:1)

我假设你检查过你是否有cpu或ram问题。

唯一能够以“令人惊讶”的方式减慢节点的是垃圾收集器 - 尝试使用--trace*运行您的节点以查看正在发生的事情。 (见node --v8-options。)

我个人认为你没有从中找到任何东西,因为 - 这就是我的感觉 - 问题出在其他地方。

对于500ms的乘法的完美延迟,我假设你有丢包。如果这是一般性问题,您可以查看ifconfig,然后查看tcpdump数据包并查看是否重新传输。

答案 1 :(得分:0)

我知道这可能听起来很奇怪,但您认为这不是节点的问题,而是操作系统设置。您是否检查了文件句柄以及操作系统向套接字显示的连接数?您是否还确保操作系统中的套接字超时足够低?我遇到了与其他代码类似的声音性能问题,结果证明是操作系统,而不是代码。还要检查软件包,看看它对套接字上允许打开的连接有什么作用。我没有查看节点代码,但遇到了与java中的http客户端库类似的问题。应用程序刚刚备份,这只是连接数量的配置问题。

答案 2 :(得分:0)

你之所以看到这是因为Nagle的算法。这是一种在I / O上使用的算法,它缓冲数据一段时间,然后发送更大的数据块。它用于保存传输(在套接字中)。您可以在http://en.wikipedia.org/wiki/Nagle's_algorithm

了解更多相关信息

要禁用Nagle的算法(当你想尽快发送大量小请求时很好)你可以做socket.setNoDelay(true);如果你正在使用net.Socket()。在socket.io的情况下,我认为Nagle已默认为Websockets禁用,但不一定适用于其他协议。我建议使用来自node.js的net.Sockets运行测试,禁用Nagle并查看你得到的内容。