多个 Socket.io 应用程序进程导致每个客户端套接字反复连接和断开连接

Multiple Socket.io app processes cause each client socket connects and disconnects repeatedly

我正在使用 Socket.io 开发一个 nodejs 应用程序,我使用 PM 2 在单个进程中进行了测试,没有错误。然后我转到我们的生产环境(我们使用 Google 云计算实例)。

我 运行 3 个应用程序进程和一个 iOS 客户端连接到服务器。 顺便说一下,iOS 客户端不保持套接字连接。它不会向服务器发送断开连接。但是它已断开连接并重新连接到服务器。它不断发生。

我不确定服务器为什么会断开客户端连接。 如果您对此有任何提示或答案,我将不胜感激。

这可能是因为请求最终到达了另一台机器,而不是它们的来源机器。

直接来自Socket.io Docs: Using Multiple Nodes

If you plan to distribute the load of connections among different processes or machines, you have to make sure that requests associated with a particular session id connect to the process that originated them.

您需要做的事情:

  • 启用 session affinity、a.k.a 粘性会话
  • 如果您想使用 rooms/namespaces,您还需要使用集中式内存存储来跟踪命名空间信息,例如 Redis/Redis Adapter.

但我建议您阅读我发布的文档,自从我上次实现类似内容以来,情况可能有所改变。

默认情况下,socket.io 客户端 "tests" 通过几个 http 请求断开与其服务器的连接。如果您有多个服务器请求并且这些初始 http 请求每次都不会发送到完全相同的服务器,那么 socket.io 连接将永远无法正确建立并且不会切换到 webSocket 并且它将继续尝试使用http 轮询。

有两种方法可以解决这个问题。

  1. 您可以将客户端配置为假定 webSocket 协议可以正常工作。这将启动与一个并且只有一个 http 连接的连接,然后将立即升级到 webSocket 协议(最重要的是 socket.io 运行)。在 socket.io 中,这是与初始连接一起指定的 transport 选项。

  2. 您可以将服务器基础结构配置为粘性的,以便来自给定客户端的请求始终返回到完全相同的服务器。有很多方法可以做到这一点,具体取决于您的服务器架构以及服务器之间的负载平衡方式。

如果您的服务器将任何客户端状态保存在服务器本地(而不是在所有服务器访问的共享数据库中),那么您甚至需要断开连接并重新连接以返回到同一服务器,您将需要粘性连接作为您唯一的解决方案。您可以在 socket.io 网站 here.

上阅读有关粘性会话的更多信息

感谢您的回复。

我终于弄明白了。该问题是由 Google Cloud Load Balancer 中后端服务的 TTL 引起的。默认的 TTL 是 30 秒,它使每个套接字连接都尝试断开连接并重新连接。

所以我将值更新为 3600s 然后我可以保持连接。