【问题标题】:High Latency with NodeJSNodeJS 的高延迟
【发布时间】:2013-06-19 06:34:19
【问题描述】:

这个问题与 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')
})

我有一个带有 socket.io 的简单空白 HTML 页面,它会定期发送一个 perf 事件以及回调触发所需的时间。它仍然显示相同的内容:

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

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

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

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

无论如何,这几个月来一直让我感到困惑,我真的很想了解导致它的原因以及如何解决它。

【问题讨论】:

  • 我很好奇你是否可以直接在服务器上打开一个本地连接(可能使用 phantomjs 之类的东西)并执行相同的测量,如果你会看到类似的尖峰。我也很好奇您使用的是什么版本的浏览器,以及是否有任何版本退回到 Flash、长轮询或 iframe。看起来你在没有会话的情况下运行 express,所以它似乎不是与会话相关的 GC 或类似的东西,并且你肯定服务器没有重新启动或任何东西(这可能会显示所有浏览器的峰值)在同一时间,所以可能不是,但只是问)。
  • 我猜您在这些期间也已经在监控服务器统计信息了?好奇内存或 cpu 是否同时存在任何相关的峰值或下降。如果您可以访问数据中心,您可以插入那里的本地交换机并消除大部分网络干扰,但这可能不是一个选择......如果他们从数据内部提供 socket.io 监控服务会很好中心。
  • 实际上,您可以编写一个本地 socket.io 节点客户端并在同一服务器上本地运行它,并对其进行测量。很抱歉给你发了这么多垃圾邮件,性能问题就像大海捞针一样,所以只是尝试扔掉我能想到的所有东西可能有助于将问题缩小到某个特定区域。
  • 您是否尝试在自己的本地服务器上运行它以查看是否是节点的问题?
  • 您是否尝试过不同的实现,可能使用 pubnub 或类似的服务。您将能够缩小问题的范围。你也没有回答上面关于在本地尝试的评论吗?

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


【解决方案1】:

我假设您检查了是否有 cpu 或 ram 问题。

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

我个人认为你不会从中发现任何东西,因为 - 这只是我的感觉 - 问题出在其他地方。

有了 500 毫秒的完美延迟,我假设您有数据包丢失。如果这是一般问题,您可以通过ifconfig 检查数据包,然后检查数据包是否重新传输。

【讨论】:

  • 虽然我只对节点做了一点,但我已经编写了相当多的 Java 服务器代码。我们担心延迟的主要问题之一是垃圾收集。许多基于 VM 的语言(如 Javascript/Node)的问题在于,延迟只能在 VM 允许的范围内预测。在 Java 的情况下,我们经常努力减少垃圾收集,不是因为延迟,而是因为延迟峰值。以防万一,我肯定会看看 GC。
【解决方案2】:

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

【讨论】:

    【解决方案3】:

    你看到这个的原因是因为 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 并看看你得到了什么。

    【讨论】:

    • Nagle 仅在每个连接的基础上工作,并将小包连接到大包。这不可能是这里的问题,因为您每次通话都有一个新的连接。只有当您拥有实时流式传输时,Nagle 才会成为问题。
    猜你喜欢
    • 2021-12-20
    • 2017-09-03
    • 2016-07-23
    • 2015-08-07
    • 2014-06-02
    • 1970-01-01
    • 2021-12-19
    • 2017-07-05
    • 1970-01-01
    相关资源
    最近更新 更多