在 `binance_client`、`kline_stream`、`book_ticker_stream` 和 `ticker_24h_stream` 中引入 Redis 缓存支持,允许 Leader 进程写入数据,其他进程从 Redis 读取,提升数据获取效率。更新了相关逻辑以确保在多进程环境下的稳定性和一致性,同时增强了异常处理和日志记录,确保系统的可追溯性。
6.7 KiB
6.7 KiB
WebSocket 共用与币安限频评估
一、币安合约 WS 限制(摘要)
- Base URL:
wss://fstream.binance.com - 单 stream:
/ws/<streamName> - 组合 stream:
/stream?streams=/<streamName1>/<streamName2>/... - 单连接最多订阅:1024 个 Streams
- 订阅限速:每秒最多 10 条订阅消息,超限会断连;反复断连的 IP 可能被屏蔽
- 连接有效期:单连接不超过 24 小时,需断线重连
- Ping/Pong:服务端约 3 分钟发 ping,客户端需在 10 分钟内回复 pong(当前 aiohttp heartbeat 已满足)
二、当前系统 WS 使用方式(按进程)
当前为 一进程一账户(如 supervisor 按 ATS_ACCOUNT_ID 起多个 trading_system 进程),每个进程内:
| 用途 | 连接数/进程 | 订阅内容 | 是否公开 | 可否多账户共用 |
|---|---|---|---|---|
| UserDataStream | 1 | listenKey(订单/持仓/余额) | 否(需 listenKey) | 否,每账户必须独立 |
| Ticker24hStream | 1 | !ticker@arr(全市场 24h ticker) |
是 | 可共用,全市场一份即可 |
| BookTickerStream | 1 | !bookTicker(全市场最优买卖) |
是 | 可共用,全市场一份即可 |
| KlineStream | 1 | /stream + 动态 SUBSCRIBE:<symbol>@kline_<interval> |
是 | 可共用,按需订阅,单连接 ≤1024 streams |
| 持仓价格监控(position_manager) | 每持仓 1 条 | 每连接 /ws/<symbol>@ticker |
是 | 可共用,可合并为一条组合流 |
即:每账户 4 条固定连接 + 持仓数个单独连接。
三、多账户时的连接与订阅量(当前架构)
设账户数为 N,单账户最大持仓数为 M(如 10):
- UserDataStream:N 条(每账户 1,不能省)
- Ticker24hStream:N 条 → 若共用为 1 条
- BookTickerStream:N 条 → 若共用为 1 条
- KlineStream:N 条,每连接动态订阅若干
symbol@kline_interval→ 若共用为 1 条,总 streams 数为「所有账户用到的 (symbol, interval) 并集」 - 持仓监控:N × M 条(每持仓一个
/ws/<symbol>@ticker)→ 若合并为一条组合流,为 1 条连接,streams 数为「所有账户持仓的 symbol 并集」,且 ≤1024
当前是否超限:
- 1024 streams/连接:单条 KlineStream 当前按「扫描/策略用到的 symbol×interval」订阅,通常几十~小几百级,远低于 1024;持仓监控若合并为一条组合流,symbol 数一般也远小于 1024。正常使用不会超。
- 10 条订阅/秒:KlineStream 在扫描时可能对多个 symbol×interval 连续调用
subscribe,若并发高会短时间多发订阅消息,有超过 10 条/秒的风险,存在被断连、进而 IP 被限的风险。需要限速(见下文实现)。
四、可共用的流与建议
1. 强烈建议共用(公开、全市场一份即可)
-
Ticker24hStream(
!ticker@arr)- 全市场 24h 行情,与账户无关。
- 建议:单机多进程时,可由一个「行情进程」或主进程单独起 1 条连接,写入 Redis/共享缓存,其他进程只读缓存;或若已用 Redis 等共享缓存,仅一个进程负责拉 WS 并更新缓存。
-
BookTickerStream(
!bookTicker)- 全市场最优买卖,与账户无关。
- 建议:同上,共用 1 条连接 + 共享缓存。
2. 建议共用(减少连接与 stream 总数)
-
KlineStream(
<symbol>@kline_<interval>)- 按 (symbol, interval) 动态订阅,单连接最多 1024 streams。
- 多账户共用 1 条连接时,订阅集合为「各账户用到的 (symbol, interval) 并集」,通常仍远小于 1024。
- 建议:单机多进程时,可只在一个进程内起 KlineStream,其他进程通过 Redis/共享内存读 K 线缓存;或部署一个共享「K 线 WS 服务」供多进程使用。
-
持仓监控(
<symbol>@ticker)- 当前实现为「每持仓 1 条
/ws/<symbol>@ticker」,多账户×多持仓会变成 N×M 条连接。 - 建议:改为一条组合流:
/stream?streams=s1@ticker/s2@ticker/...,把所有需要监控的 symbol 放在一起,总 symbol 数 <1024 即可。多账户可共用这一条连接(订阅「所有账户持仓 symbol 的并集」),每个账户只消费自己关心的 symbol 即可。
- 当前实现为「每持仓 1 条
3. 不能共用
- UserDataStream(listenKey)
- 与账户绑定,每账户独立 listenKey、独立连接。必须每账户 1 条连接。
五、限频与实现建议
1. 订阅消息 ≤10 条/秒(必须遵守)
- KlineStream 在
subscribe(symbol, interval)时向同一连接发送 SUBSCRIBE。 - 若扫描阶段并发请求多个 symbol×interval,会在短时间连续发送多条订阅,容易超过 10 条/秒。
- 实现:在 KlineStream 内做订阅限速:例如维护「最近 1 秒内已发送的订阅次数」,若已达 10 次则 sleep 到「满 1 秒」后再发;或批量排队,按每秒最多 8~10 条发送。
- 已在代码中为 KlineStream 增加限速逻辑(见下节)。
2. 单连接 1024 streams
- 当前 KlineStream 与持仓监控的 stream 数量均远低于 1024,只需在后续若「预订阅」大量 symbol×interval 或大量持仓时,确保单连接订阅数 ≤1024 即可(可做订阅数统计与上限检查)。
3. 连接 24 小时
- 现有各 WS 均有断线重连,满足「不超过 24 小时」的文档要求;保持即可。
六、结论与风险
| 项目 | 当前是否可能超限 | 说明 |
|---|---|---|
| 单连接 1024 streams | 否 | 当前 K 线与持仓监控订阅量远低于 1024 |
| 10 条订阅/秒 | 是(有风险) | KlineStream 扫描时可能短时大量 subscribe,已加限速 |
| 连接数 | 否 | 多账户时连接数线性增长,共用后可显著下降 |
| 24h / Ping-Pong | 否 | 已重连 + heartbeat |
已实现:
- KlineStream 订阅限速:发送 SUBSCRIBE 时控制在 ≤10 条/秒。
- 多进程/多账户共用 Ticker24h、BookTicker、KlineStream:
- 使用 Redis 选主(
market_ws_leader):仅 Leader 进程建立上述三条 WS 连接并写入 Redis。 - 非 Leader 进程不建这三条连接,通过 Redis 刷新任务(Ticker24h/BookTicker 每 2 秒从 Redis 拉取)和 get_klines 时读 Redis 获取数据。
- 配置项
USE_SHARED_MARKET_WS(默认 true):有 Redis 时启用共用;关闭则每进程独立建连接。
- 使用 Redis 选主(
- 持仓监控:仍为每进程按持仓建多条
/ws/<symbol>@ticker;后续可改为单连接组合流并共享(未实现)。