2013-06-22 55 views
13

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

总之,测试了这一点(并确保它不是由于我的游戏的代码),我建立了一个最小的测试案例:

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页面插座。 io会定期发送一个perf事件和时间来回复触发所花费的时间。和它仍然显示同样的事情:

graph showing lag spike

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

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

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

从左至右:Chrome隐身,铬(常规),火狐,Chrome(常规)

charts on four windows

无论如何,这已经困惑我几个月,我真的想明白了什么导致它,以及如何解决它。

+1

我很好奇,如果你可以直接在服务器上打开本地连接(也许有类似phantomjs的东西),并执行相同的测量,如果你会看到类似的尖峰或不。我也很好奇你使用的是什么版本的浏览器,以及是否有闪回,长轮询或iframes。看起来你正在运行没有会话的快递,所以它似乎不是会话相关的GC或类似的东西,你肯定服务器没有重启或任何事情(这可能会显示在所有浏览器同一时间,所以可能不会,但只是问)。 – hoonto

+0

我猜你在这期间已经监视了服务器的统计数据?好奇的是,如果在同一时间有任何相关的尖峰或内存或CPU下降。如果您有权访问数据中心,则可以在那里插入本地交换机并消除大部分网络干扰,但这可能不是一种选择......如果他们从数据中提供了socket.io监控服务中央。 – hoonto

+1

实际上,你可以编写一个本地的socket.io节点客户端,并在同一台服务器上本地运行它,并对其进行度量。对不起,垃圾邮件你太多了,性能问题可能就像干草堆里的针,所以只是试图抛出我能想到的一切,这可能有助于将问题缩小到某个特定区域。 – hoonto

回答

0

我知道这可能听起来很奇怪,但你认为这不是节点的问题,但与操作系统设置。你有没有检查你的文件句柄和操作系统显示给套接字的连接数量?你是否也确保操作系统中的套接字超时足够低?我遇到了与其他代码类似的声音性能问题,它变成了操作系统而不是代码。同时检查包并查看它在套接字上的打开允许连接的功能。我没有看过节点代码,但遇到了与java中的http客户端库类似的问题。刚刚备份的应用程序只是连接数量的配置问题。

1

我假设你检查了你是否有CPU或RAM问题。

能够以“令人惊讶”的方式减慢节点的唯一一件事就是垃圾收集器 - 试着用--trace*来运行节点,看看发生了什么。 (见node --v8-options。)

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

由于500毫秒的乘法的完美延迟,我假设你有一个数据包丢失。你可以用ifconfig查看是否是一般性问题,然后是tcpdump这些数据包,看看它们是否重发。

+0

虽然我只用了一点节点,但我已经写了一些Java服务器代码。我们担心延迟的主要原因之一是垃圾收集。许多基于虚拟机的语言(如Javascript/Node)的问题是延迟只能像虚拟机允许的那样预测。在Java的情况下,我们通常会努力减少垃圾收集,而不是因为延迟,而是因为延迟尖峰。以防万一,我肯定会看一下GC。 – sasbury

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并查看你得到了什么。

+3

Nagle只在每个连接的基础上工作,并将小包连接成大包。这不是问题,因为您为每次通话建立了新的连接。当你有实时流媒体时,Nagle只能成为一个问题。 – CFrei