腾讯云 CLB 四层监听后端是 WebSocket 服务,客户端每隔十几分钟断一次,抓包看到断开前没有 FIN 只有一个 RST,CLB 的连接空闲超时用的是默认 900 秒。

一开始怀疑是「后端 keepalive 时间和 CLB 不一致,先被后端关掉」,查了一圈,方向不对。

排查方向其实有限,先把可能性排一排。连接长时间没有数据,CLB 按空闲超时直接回收。还有一种是客户端心跳间隔大于 900 秒,来不及续命。

另外,中间 NAT 设备映射表过期,回包被丢弃。

先看连接空闲时长和断开方式

ss -tn state established '( sport = :8080 )' | head

然后把心跳间隔压到超时的一半

grep -i heartbeat /etc/app/websocket.conf

调整 CLB 的空闲超时时间

tccli clb ModifyLoadBalancerAttributes --LoadBalancerId lb-xxxx --InternetChargeType TRAFFIC_POSTPAID_BY_HOUR

后端开 TCP keepalive 再验证

sysctl -w net.ipv4.tcp_keepalive_time=300

手上没有现成的复现脚本,就照着线上请求手工拼了一个。

别只看报错消失,验证要多做一步。长连接持续两小时不断开,抓包里能看到周期性心跳,客户端不再报连接重置。

提醒一点。四层空闲超时和七层的 keepalive_timeout 是两套参数,只改一侧还是会在另一侧被断。如果同一现象隔几天又出现,说明根因没找到,别当偶发处理。

作者 9823189