繁体   English   中英

NodeJS的高延迟

[英]High Latency with NodeJS

这个问题特别适用于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事件,并计算回调触发所需的时间。 它仍然显示相同的事情:

显示滞后峰值的图形

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

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

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

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

四个窗口上的图表

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

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

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

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

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

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

你之所以看到这是因为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并查看你得到的内容。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM