应优先使用 WebSocket 标准 ping/pong 帧而非自定义 message,因其最轻量、合规且不易被代理丢弃;websockets 库通过 pings_interval 和 ping_timeout 参数控制,需注意参数名是复数且单位为秒。

WebSocket心跳包该用 ping 还是自定义 message?
Python 的 websockets 库原生支持标准 WebSocket ping/pong 帧,这是最轻量、最合规的心跳方式。别自己造 JSON 格式的心跳消息——它会占用额外带宽、增加解析开销,还可能被中间代理(如 Nginx)静默丢弃。
实操建议:
立即学习“Python免费学习笔记(深入)”;
-
websockets默认每 20 秒发一次ping,超时 20 秒未收到pong就断连;可通过pings_interval和ping_timeout参数调整 - 若服务端不响应标准
pong(比如某些老旧 Java 实现),才考虑退而求其次:用asyncio.create_task()定期发自定义message,并监听对应ack - 切勿在
on_message回调里直接处理心跳逻辑——容易阻塞主协程,应交由独立任务或队列异步处理
为什么 websockets 的 ping_interval 不生效?
常见错误是把参数名写成 ping_interval 或 ping_interval_sec——正确参数名是 pings_interval(注意是复数 pings),且单位是秒(float),不是毫秒。
实操建议:
立即学习“Python免费学习笔记(深入)”;
- 启动连接时显式传参:
await websockets.connect(url, pings_interval=30.0, ping_timeout=10.0) - 若使用
serve()启动服务端,同样需设置pings_interval,否则客户端发来的ping可能得不到响应 - 检查 Python 版本:低于 10.4 的
websockets不支持pings_interval,会静默忽略该参数——升级到websockets>=11.0更稳妥
心跳失败后如何避免重复重连或资源泄漏?
心跳超时触发的 ConnectionClosedError 是正常断连信号,但直接在 except 块里调用 connect() 重试,极易造成“雪崩式重连”或未关闭的 socket 积压。
让 macOS 自动化像说话一样简单 —— 用代码控制你的 Mac,无需学习 AppleScript 系统要求 macOS 14+ (Sonoma) Python 3.9+ 需要开启:辅助功能 + 屏幕录制权限
实操建议:
立即学习“Python免费学习笔记(深入)”;
- 捕获
websockets.exceptions.ConnectionClosedError和asyncio.TimeoutError,而非宽泛的Exception - 重连前加指数退避:
await asyncio.sleep(min(2 ** attempt, 60)),防止高频冲击服务端 - 每次重连前确保旧连接已 close:显式调用
websocket.close()并 await,再检查websocket.closed状态 - 用
asyncio.wait_for()包裹 connect 调用,防止 DNS 卡死或服务端无响应导致整个协程挂起
Django Channels 或 FastAPI 中怎么统一管理 WebSocket 心跳?
框架封装了连接生命周期,直接在 handler 里手动发 ping 会和框架内部心跳冲突。必须走框架提供的钩子或配置项。
实操建议:
立即学习“Python免费学习笔记(深入)”;
- Django Channels:在
consumers.py的connect()方法里,通过self.scope['session']记录心跳时间戳;用asyncio.create_task(self._heartbeat_loop())启动独立任务,发自定义心跳 message(因 Channels 不暴露底层ping控制权) - FastAPI +
starlette.websockets:直接用原生websockets的pings_interval,但需绕过 FastAPI 的WebSocket类——改用websockets.connect()手动建连,否则框架默认禁用ping - 无论哪种框架,都不要在
disconnect()里做耗时清理(如 DB 写入),应发信号给后台任务处理,避免阻塞 WebSocket 关闭流程
真正难的不是发心跳,而是判断“心跳没回”到底是网络抖动、服务端卡死,还是对方已下线。这时候 ping_timeout 和业务层 ACK 必须配合使用——前者保连接存活,后者保业务可达。漏掉任意一环,长连接就只是看起来稳而已。

















