【问题标题】:Sockjs/socketio disconnect delay behind apache proxyApache 代理背后的 Sockjs/socketio 断开延迟
【发布时间】:2017-10-20 13:26:36
【问题描述】:

我需要处理与我的 sockjs 应用程序断开连接的用户在 xhr-polling 模式下运行。当我连接到本地主机时,一切都按预期工作。当我将 apache 放在 nodejs 和浏览器之间时,我在关闭浏览器和 nodejs 内的断开事件之间得到约 20 秒的延迟。我的 apache 代理配置如下:

<Location />
  ProxyPass http://127.0.0.1:8080/
  ProxyPassReverse http://127.0.0.1:8080/
</Location>

文件的其余部分是默认的,你可以看到它here。我尝试使用 ttl=2 和 timeout=2 选项,但要么没有任何变化,要么我每 2 秒重新连接一次而不关闭浏览器。我怎样才能减少额外的断开超时,引入,但 apache,在其默认值的某个地方?

【问题讨论】:

  • sockjs 首先尝试 websockets,如果不可用,则使用轮询。当您将 apache 放在两者之间时,您只传递了 http,因此您不允许 ws 协议,因此强制进行轮询。如果您在 apache 文件中启用 mod_proxy_wstunnel 会怎样,如此处所述...httpd.apache.org/docs/2.4/mod/mod_proxy_wstunnel.html
  • @bpursley,请仔细阅读问题,没有 apache,我没有任何 websocket 数据传输,因为我禁用了 websockets。
  • 您是否意识到检测与 xhr-polling 断开连接的唯一方法是超时?您只需要知道客户端轮询间隔设置为什么并将服务器超时设置为比客户端轮询间隔更长的时间,因此如果您在一段时间后没有看到任何客户端再次返回轮询,那么您假设客户端必须已断开连接。由于轮询工作的本质,没有什么好方法可以在所有情况下及时断开轮询。
  • 不,可以处理断开连接,在nodejs中你可以注册这个回调:req.on('close',function(){console.log("byby")})。即使 sockjs 里面有 1s 超时或者心跳,我也不希望 apache 给它加 20 秒。
  • @StepanYakovenko 您是否启用了 HTTP 保持活动?

标签: node.js apache socket.io long-polling


【解决方案1】:

您的 Apache 服务器可能配置为使用 HTTP Keep Alive,这将保持持久连接打开。在这种情况下,我会尝试禁用 KeepAlive,或降低 Apache 配置中的 KeepAliveTimeout 设置,看看是否能解决问题。

如果这不起作用,我还会查看netstat 并查看每个套接字的状态并开始根本原因分析。这个chart 给出的是 TCP 状态机,它可以告诉你每个连接在哪里。 Wireshark 还可以为您提供一些有关正在发生的事情的信息。

【讨论】:

  • @jfriend00 如果你想添加一些东西,这次请尊重。
  • 试过 Keepalive Off 和调整 KeepAliveTimeout 10,它没有帮助。此外,如果您查看 ProxyPass 文档,默认情况下会禁用 keepalive 选项。
【解决方案2】:

在长轮询中,连接发生如下

<client> ---> apache ---> <node.js>

当客户端断开连接时

<client> -X-> apache ---> <node.js>

Apache 仍然保持连接打开。现在有两种解决方法

代理超时

您可以将以下内容添加到您的 apache 配置中

ProxyTimeout 10

这将在 10 秒后中断连接,但随后会在 10 秒后中断每个长轮询连接,这是您不希望的

Ping

下一个选项是 ping 客户端

pingTimeout (Number):没有pong包多少毫秒认为连接关闭(60000)

pingInterval (Number):在发送新的 ping 数据包之前多少毫秒 (25000)。

var io = require('socket.io')(server, { 'transports': ['polling'], pingTimeout: 5000, pingInterval: 2500});

以上将确保客户端在关闭后 5 秒内断开连接,您可以再次降低它,但这可能会影响通常的加载场景

但是阅读所有帖子、线程和站点,我认为您无法复制直接连接到socket.io 时的行为,因为socket.io 可以轻松检测到连接中断

【讨论】:

    【解决方案3】:

    20 秒延迟不在 apache 代理中。我遇到了同样的问题,本地 URL 中没有延迟,但全局 URL 中发生了延迟。

    这个问题在 NodeJs 本身中得到了解决。需要从服务器向客户端发送一次数据以确保其已初始化。这个问题不在 WebSocket 插件的文档和问题博客中。

    在服务器接受请求后发送虚拟消息,如下所示。

    let connection = request.accept(null, request.origin);
    
    connection.on('message', function (evt) {
        console.log(evt);
    });
    
    connection.on('close', function (evt) {
        console.log(evt);
    });
    
    connection.send("Success"); //dummy message to the client from server
    

    【讨论】:

    • 问题是关于 sockjs,而不是 websocket
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-11-13
    • 2017-01-23
    • 2015-04-14
    • 2015-12-25
    • 1970-01-01
    • 2017-07-09
    • 1970-01-01
    相关资源
    最近更新 更多