Python websockets对接币安合约场景下内存泄漏问题排查求助
内存泄漏成因
- 依赖库版本存在已知bug:你当前使用的
websockets==9.1是2021年发布的老旧版本,该版本存在明确的连接重建场景下的内存泄漏问题:旧连接销毁时,协议层的帧数据、解码缓存没有被正确解除引用,无法被GC自动回收。你每50分钟重建一次连接的逻辑,会持续累积旧连接的残留内存,从tracemalloc的计数也能看出,2小时累计300多万个未释放的帧对象,和你接收的数据包数量完全匹配。 - 封装库资源清理逻辑缺陷:
unicorn-binance-websocket-api==1.31.0版本的replace_stream方法存在资源泄漏,调用该方法时仅新建了流实例,没有彻底清理旧流关联的websockets协议实例引用,导致旧连接的所有帧数据一直被持有,无法释放。 - 业务代码潜在引用持有:如果你的业务逻辑中直接将原始消息对象(而非拷贝后的业务数据)存储到全局列表、缓存、异步队列中长期持有,也会关联持有底层帧数据的引用,阻碍内存回收。
排查与解决建议
- 优先升级依赖版本
- 将
websockets升级到10.0及以上稳定版本,官方在10.0版本中修复了多个协议层内存泄漏问题,其中就包含你观测到的protocol.py行834的帧数据未释放问题。 - 将
unicorn-binance-websocket-api升级到最新稳定版,该库后续版本已修复replace_stream方法的资源清理缺陷,旧流关联的所有资源会被正确释放。
- 将
- 临时规避方案(若暂时无法升级依赖)
- 放弃使用
replace_stream方法重建连接,改为分三步操作:先调用stop_stream停止旧流,再调用delete_stream彻底删除旧流实例及关联资源,最后调用create_stream新建连接,避免旧资源残留。 - 每次完成旧连接清理后,手动调用
gc.collect()强制触发垃圾回收,验证内存占用是否可以回落,确认泄漏是否由引用未自动释放导致。
- 放弃使用
- 业务代码排查
- 检查消息处理逻辑,不要直接持有原始websocket消息对象,仅提取需要的业务字段存储,解除对底层帧对象的关联引用。
- 检查异步逻辑中是否存在未正确完成的协程,避免协程上下文长期持有消息对象的引用。
内容的提问来源于stack exchange,提问作者Dima
相关产品推荐
相关产品推荐

