opensumi / core

🚀 A framework helps you quickly build AI Native IDE products.
https://opensumi.com
MIT License
3.01k stars 386 forks source link

[BUG] websocket 重连后,有一定概率前后端不可交互 #2919

Open piLurk opened 1 year ago

piLurk commented 1 year ago

描述你的问题(Describe the bug) 在 websocket 重连后,有两个长连接,有一定概率前后端不可交互

image

看下下代码,依赖了一个 reconnecting-websocket 包, 直接在创建长连接时就释放 block 了,是不是需要等上一个长连接请求 close 或者 error image

复现路径(To Reproduce)

  1. 断网到 触发 websocket 重新连接
  2. 打开网络
  3. 有一定概率前后端不可交互

预期表现(Expected behavior) websocket 重连后,前后端可交互

piLurk commented 1 year ago

@pipiiiiii @erha19 好像这里还有另一个问题,在断网或者休眠时,有一定概率丢失请求数据。 image

这块 websocket 超时需要 120s,但是期间 this._ws.readyState 还是ok的,在此期间前端的发的请求不会放到 _messageQueue,如果 websocket 超时, 会丢失这部分数据。

piLurk commented 1 year ago

补充一个数据丢失引发的副作用,期间前端的状态已经变化,但是后端没有收到,前后端状态不一致。 此时例如文件展开,文件打开,都无法正常进行了。 image

上诉前后端不可交互由此引发。和 connect lock 应该无关

pipiiiiii commented 1 year ago

@piLurk 由于重连导致的一些问题之前修过一些

pipiiiiii commented 1 year ago

如果想要调试重连的问题,可以在 https://github.com/opensumi/core/blob/main/packages/core-browser/src/bootstrap/connection.ts#L61 这里主动调用重连

setTimeout(() => {
    // @ts-ignore
    wsChannelHandler.connection.reconnect();
  }, 30 * 1000);
piLurk commented 1 year ago

@pipiiiiii 业务层有做数据恢复么,我理解可能还不能解决这个问题。。 这里的本质问题是reconnecting-websocket 这个包对于 websoket 是否可用完全是依赖 readyState 来做检查,但是除此之外,网络波动/休眠/切换网络/服务拥塞 等 都会引发 websoket 不可用。 此时在不可用的 websoket 连接中已经发送了一些数据,这些数据就会丢失

image

pipiiiiii commented 1 year ago

@pipiiiiii 业务层有做数据恢复么,我理解可能还不能解决这个问题。。 这里的本质问题是reconnecting-websocket 这个包对于 websoket 是否可用完全是依赖 readyState 来做检查,但是除此之外,网络波动/休眠/切换网络/服务拥塞 等 都会引发 websoket 不可用。 此时在不可用的 websoket 连接中已经发送了一些数据,这些数据就会丢失

image

目前并没有做数据恢复,增加超时时间可以防止发出去没有消息返回导致代码一直等待执行的问题。 如果需要数据恢复,我理解在发送消息时根据业务逻辑处理比较好,因为现在 node 端在连接断开时会 disposeAll,仅仅重发消息不一定能解决问题

erha19 commented 1 year ago

对于没有返回值的 WS 消息,是不是可以有个 buffer 缓存,再重连阶段重新发一下(目前好像是超时直接返回,有点矛盾)

pipiiiiii commented 1 year ago

https://github.com/opensumi/core/blob/main/packages/core-node/src/connection.ts#L50 这里做了 disposeAll 处理,如果是因为断连导致的无返回值,仅仅重发不一定会符合预期,因为这个时候如果获取到消息返回值,后续执行逻辑的一些实例可能已经被销毁了

pipiiiiii commented 1 year ago

不过或许可以在断连时将已经发出的去消息全部 reject ,不用等超时