在 `binance_client`、`kline_stream`、`book_ticker_stream` 和 `ticker_24h_stream` 中引入 Redis 缓存支持,允许 Leader 进程写入数据,其他进程从 Redis 读取,提升数据获取效率。更新了相关逻辑以确保在多进程环境下的稳定性和一致性,同时增强了异常处理和日志记录,确保系统的可追溯性。
114 lines
6.7 KiB
Markdown
114 lines
6.7 KiB
Markdown
# 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 即可。
|
||
|
||
### 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 |
|
||
|
||
**已实现:**
|
||
|
||
1. **KlineStream 订阅限速**:发送 SUBSCRIBE 时控制在 ≤10 条/秒。
|
||
2. **多进程/多账户共用 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 时启用共用;关闭则每进程独立建连接。
|
||
3. **持仓监控**:仍为每进程按持仓建多条 `/ws/<symbol>@ticker`;后续可改为单连接组合流并共享(未实现)。
|