Skip to content

[Bug]: 两个 WebSocket 质量问题(资源泄漏 + 日志中泄露密钥) #9

@axlnur

Description

@axlnur

[Bug]: 两个 WebSocket 质量问题(资源泄漏 + 日志中泄露密钥)

在使用 github.com/banbox/banexg 进行长期部署时,发现两个独立的问题。


问题 1:WebSocket 客户端注册表无界增长

概述

当 WebSocket 客户端关闭时,并未从交易所的内部客户端注册表中移除。虽然关闭回调路径上执行了部分相关清理逻辑,但注册表条目本身会在整个进程生命周期内一直留存。

触发场景

  • 在 Binance USDM 上,每次 listenKey 轮换都会生成一个新的客户端(URL 中嵌入了 listenKey,轮换时注册表的 key 也随之变化)。原有客户端则被遗弃在注册表中。
  • 短暂重连也会出现相同的现象:旧条目残留,新条目被添加到另一个 key 下。

影响

随着 WS 客户端的更替频率(重连、listenKey 轮换),内存会出现缓慢的单调增长。每个残留条目都会持有一个 client 结构体及其已关闭的连接。短期内不会致命,但在 7x24 小时持续运行数天乃至数周后即可观察到。

修复建议

在现有的关闭清理路径中一并将该条目从注册表中移除。由于注册表当前在多个 goroutine 之间被无锁地修改,借此修改顺便引入同步机制,使并发访问变得安全。


问题 2:Binance 的 listenKey 以明文形式写入日志

概述

对于 Binance 用户数据流,WebSocket URL 中会嵌入 listenKey——在旧主机上作为路径段,在新的 /private/ws 主机上则作为查询参数。该 URL 字符串随后会在多个层级被打日志:连接、重连、关闭、调试级别的读写,以及 listenKey 续期流程中的告警路径。

影响

listenKey 的有效期较短(约 60 分钟),且只授予对单个账户用户数据流的只读访问权限,因此严重程度较低。但它毕竟是会话凭证,不应以明文形式出现在任何可能被读取日志的位置:日志文件、聚合服务(Loki、ELK、Datadog 等)、错误追踪平台,以及附在工单中的截图等。

修复建议

在 WebSocket URL 进入 logger 之前,先将其中的 listenKey 部分脱敏。需要处理两种形态:旧主机上末尾的路径段,以及新的 /private/ws 上的 listenKey=<value> 查询参数。

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions