现象
在有轻微丢包的网络上,bridge 会频繁误判 WebSocket "卡死" 并强制重连。重连期间收到的消息被 policy.denied code=reconnect-in-progress 丢弃,用户侧表现为收到「当前 bot 正在重连,稍后会继续处理新消息。」,且消息实际丢失(不是排队)。
一台机器 3 小时内的实测计数:
正在重连 25
ENOTFOUND 23
network.unreachable 12
keepalive.ws-stuck 37
force-reconnect 7
no pong 19
policy.denied 9
根因
dist/cli.js 给 SDK 传了 pingTimeout: 3,而 ping 间隔由服务端下发,实测默认 120 秒:
// dist/cli.js
pingTimeout: 3
// @larksuiteoapi/node-sdk
this.ws = { pingInterval: 120 * 1000, ... }
SDK 侧 pingTimeoutSec 默认是 0(不启用看门狗),这个 3 秒是 bridge 主动开启的。
armLiveness() 在每次发 ping 后启动看门狗,任何入站帧会 clearLiveness()。也就是说:连接空闲时,只要一个 ping 或 pong 丢包,3 秒后就会 terminate() 掉一条健康的连接。
同机实测网络质量:
ping 网关 0.0% 丢包 3.4ms
ping open.feishu.cn 3.3% 丢包 7.4ms
3% 丢包 + 3 秒窗口,误杀是必然的。而且重连本身还会放大问题——重连时的 DNS 查询偶发 getaddrinfo ENOTFOUND,进一步拉长不可用窗口。
建议
把 pingTimeout 提到 15–30 秒(我本地改成 20 秒)。ping 间隔 120 秒的前提下,20 秒的容错窗口仍能在最坏 140 秒内发现真正的死连接,对 IM 场景足够,同时能扛住连续丢几个包。
更好的做法是做成可配置项(profile 配置或环境变量),不同网络环境差异很大。
环境
- lark-channel-bridge 0.5.9
- macOS,Wi-Fi,公司内网 DNS
现象
在有轻微丢包的网络上,bridge 会频繁误判 WebSocket "卡死" 并强制重连。重连期间收到的消息被
policy.denied code=reconnect-in-progress丢弃,用户侧表现为收到「当前 bot 正在重连,稍后会继续处理新消息。」,且消息实际丢失(不是排队)。一台机器 3 小时内的实测计数:
根因
dist/cli.js给 SDK 传了pingTimeout: 3,而 ping 间隔由服务端下发,实测默认 120 秒:SDK 侧
pingTimeoutSec默认是0(不启用看门狗),这个 3 秒是 bridge 主动开启的。armLiveness()在每次发 ping 后启动看门狗,任何入站帧会clearLiveness()。也就是说:连接空闲时,只要一个 ping 或 pong 丢包,3 秒后就会terminate()掉一条健康的连接。同机实测网络质量:
3% 丢包 + 3 秒窗口,误杀是必然的。而且重连本身还会放大问题——重连时的 DNS 查询偶发
getaddrinfo ENOTFOUND,进一步拉长不可用窗口。建议
把
pingTimeout提到 15–30 秒(我本地改成 20 秒)。ping 间隔 120 秒的前提下,20 秒的容错窗口仍能在最坏 140 秒内发现真正的死连接,对 IM 场景足够,同时能扛住连续丢几个包。更好的做法是做成可配置项(profile 配置或环境变量),不同网络环境差异很大。
环境