通过Websockets使用Socket.io - 随机的“transport end”断开连接

8

使用

Web应用程序。NodeJS + Socket.io(仅使用websockets,启用心跳)。

问题

我的应用程序工作正常(它连接到Socket.io,正确地发出/接收消息),但我检测到随机断开连接,不是由于心跳超时。即使服务器从客户端接收到一个心跳数据包,仍然有可能在几秒钟内断开该客户端的连接。我不明白原因。它几乎是随机的,大约每3-15分钟一次。更改socket.io配置似乎不会影响频率。

这里是日志,它清楚地显示断开连接的原因是不是心跳超时,而是传输端(套接字端)

日志:

debug: emitting heartbeat for client cTVCsv2GS2R_lh3Ecao-
debug: websocket writing 2::
debug: set heartbeat timeout for client cTVCsv2GS2R_lh3Ecao-
debug: got heartbeat packet
debug: cleared heartbeat timeout for client cTVCsv2GS2R_lh3Ecao-
debug: set heartbeat interval for client cTVCsv2GS2R_lh3Ecao-
info: transport end (socket end) 
// ^ Why?
debug: set close timeout for client cTVCsv2GS2R_lh3Ecao-
debug: cleared close timeout for client cTVCsv2GS2R_lh3Ecao-
debug: cleared heartbeat interval for client cTVCsv2GS2R_lh3Ecao-
SOCK 25.12 22:23:20.675 disconnection from IO detected (USER1) 
// ^ This means disconnected event fired
debug: discarding transport
debug: client authorized
info: handshake authorized GPBLHsqhhrdsTeqTcao_
debug: setting request GET /socket.io/1/websocket/GPBLHsqhhrdsTeqTcao_?conftoken=20519986772
debug: set heartbeat interval for client GPBLHsqhhrdsTeqTcao_
debug: client authorized for
debug: websocket writing 1::
debug: client authorized for /io/activity
debug: websocket writing 1::/io/activity
SOCK 25.12 22:23:23.005 reconnected to IO (USER1)

配置

客户端:

socket = io.connect('/io/activity',{'max reconnection attempts':Infinity})

服务器:

io = require('socket.io').listen(server, { 
      log: true
    , "close timeout": 120
    , "heartbeat timeout": 120
    , "heartbeat interval": 30
    , "transports": ["websocket"]
})

io.enable('browser client minification')
io.enable('browser client etag')
io.enable('browser client gzip')

2
如果您只需要WebSockets协议,我建议使用纯WebSockets模块,而不是socket.io。Socket.io具有其他协议的层和一些“心跳”实现,但将其保留为WebSockets实际上没有意义,因为WebSockets是持久的TCP连接,在断开连接时双方都知道TCP连接丢失。因此,通过支持多个协议的需求,socket.io中的WebSockets遭受了一些额外的层次。使用https://github.com/einaros/ws进行WebSockets将更加高效。 - moka
你如何解决网络连接不稳定的问题(例如快速但不稳定)?当你关闭浏览器时,它会立即发送一个断开连接的消息,TCP 连接也会关闭。如果客户端只是关闭了 Wi-Fi 呢?如果没有心跳超时,TCP 连接将永远存在。 - igorpavlov
@igorpavlov 节点TCP已经超时:http://nodejs.org/api/all.html#all_socket_settimeout_timeout_callback,尽管我记得没有保持活动的空闲连接不会存活很长时间。 - Farid Nouri Neshat
我在Heroku上遇到了类似的问题,因为我的dynos尽管使用了WebSocket,但仍然会进入睡眠状态。这只是一个猜测。 - CharlesTWall3
这是您在本地看到的问题还是只有在与某个数据中心部署的服务通信时才会出现?我问这个问题是因为如果不是本地问题,那么您就要受制于互联网连接中使用的所有路由器和防火墙,可能是因为某个路由器认为连接已损坏,因为它打开的时间比典型的HTTP(s)连接长得多,而且只发送了一点数据。 - Cellfish
显示剩余15条评论
1个回答

0

如果我使用一个我不了解其内部工作的包,我通常会进行防御性编码。

几年前,我遇到了一些随机错误,是关于socke.io的,我只需监听错误事件并重新启动连接。请注意,某些客户端的数据可能会丢失,因此在处理错误时要小心。

查看socket.io错误可能会有所帮助。祝好运。


请看另一个关于“数据丢失”解决方案的问题:https://dev59.com/nGIj5IYBdhLWcg3wCxF0。 - igorpavlov

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接