You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python websockets保活ping超时无关闭帧,如何实现连接稳定及自动重连?

你遇到的报错本质是长连接因网络波动、代理超时等原因非正常断开,原有代码没有完善的自动重连逻辑,导致连接失效后无法恢复。可通过以下方案解决:

1. 重构客户端重连逻辑,修复原有代码缺陷

原有代码中async with websockets.connect包裹了整个数据上报循环,一旦连接断开,即使捕获了异常,当前websocket实例也已经失效,后续发送操作仍然会失败,最终会退出上下文管理器导致程序终止。
将连接逻辑放入外层死循环,每次连接断开后等待1秒自动重建连接,同时调整websocket保活参数适配上报节奏,参考代码如下:

import asyncio
import websockets
import json
import logging

# 重连等待时间(秒),可根据需要调整
RECONNECT_DELAY = 1
# 数据上报间隔
REPORT_INTERVAL = 30

async def worker(username):
    url = "{}{}/".format(LOG_SERVER, username)
    while True:
        try:
            # 显式配置保活参数,避免默认超时太短导致误判
            async with websockets.connect(
                url,
                ping_interval=10,
                ping_timeout=30
            ) as websocket:
                while True:
                    loop = asyncio.get_event_loop()
                    data = await loop.run_in_executor(None, lambda: get_data(username))
                    await websocket.send(json.dumps(data))
                    await asyncio.sleep(REPORT_INTERVAL)
        except websockets.ConnectionClosed as e:
            logging.warning(f"连接断开,即将重连: {e}")
            await asyncio.sleep(RECONNECT_DELAY)
        except Exception as e:
            logging.error(f"连接异常,即将重连: {e}")
            await asyncio.sleep(RECONNECT_DELAY)

async def main():
    username = get_username()
    await worker(username)

if __name__ == "__main__":
    asyncio.run(main())

2. 调整服务端及代理层超时配置

  • Django Channels侧不要主动断开合规的长连接,确保服务端允许websocket的ping/pong保活帧正常传输,无需设置过短的连接超时时间
  • 如果服务端前部署了Nginx、CDN等反向代理,需要将代理的websocket读超时参数proxy_read_timeout调整为60秒以上,避免代理主动切断长时间无业务数据传输的长连接

3. 增加状态防抖逻辑避免前端跳变

  • 服务端收到客户端断开通知后,延迟3~5秒再更新用户在线状态,如果这段时间内该用户重新连接成功,就不触发状态变更
  • 前端侧收到离线状态推送后,增加5秒的缓冲窗口,窗口内收到新的上报数据则取消离线状态展示,完全覆盖客户端1秒内的重连时间差

内容的提问来源于stack exchange,提问作者Elabbasy00

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.28 06:27:03