技术博客

行情分发:组播与行情代理

第 73 / 141 篇 · 2025-07-12 · secfin · 行情系统组播网络架构

行情服务器收到交易所的流之后,面对的是一个和交易完全不同的扩展性问题:行情是只读广播,同一个数据要给所有人。这篇文章讲分发的两层核心设施——组播和行情代理——以及它们各自补对方什么短板。

单播的成本模型

先看不组播会怎样。服务器对每个订阅客户端维持一条 TCP 连接,每条行情复制一份发出去。发送成本和订阅数成正比:

$$ C_{\text{unicast}} = N_{\text{client}} \times B_{\text{stream}}, \qquad C_{\text{multicast}} = B_{\text{stream}} + \epsilon $$

$B_{\text{stream}}$ 全市场 Level-2 盘中峰值轻松过 1 Gbps。单播模式下 100 个内网终端就要 100 Gbps 的网卡和交换容量,物理上不可能。组播的语义是"发一份,网络设备负责复制":服务器把包发到组播组地址(224.0.0.0/4 段),订阅者通过 IGMP 报告加入组,复制发生在交换机上,离订阅者越近的节点复制次数越多,根链路上永远只有一份。

注意组播解决的是网络内的广播效率。它建立在 UDP 上,也就继承了 UDP 的全部缺陷:不保证到达、不保证顺序、没有连接状态。行情系统对丢包的容忍度比交易高——行情丢一条靠快照恢复,不需要可靠传输——所以"不可靠"在这里恰好是特性:可靠传输的 ACK 和重传窗口本身就是延迟和状态负担。

组播落地的三个工程细节

行情专网隔离。组播流量洪峰是均值的十倍,绝不能和交易、办公流量挤一张网。券商机房通常给行情划独立 VLAN、独立网卡甚至独立交换机,防止行情洪峰把交易包挤在队列里。监管侧对交易和行情的隔离也有明确要求,检查时会看物理或逻辑隔离的实证。

频道分片。交易所把全市场按证券切成几十个频道并行发送,接收端每个频道一个线程收包、一个序列号空间。分片既是带宽分摊,也是故障隔离:一个频道出问题不影响其他频道,解析器饿死在一个频道上不会拖垮全局。

TTL 与边界控制。组播包 TTL 设小(通常 1),把广播域限制在机房内,防止组播泄漏到广域网——运营商网络里的组播是另一套协议(PIM),券商自建广域网做双机房同步时才会碰。

行情代理:最后一公里的翻译器

组播到不了公网。手机 APP 和 PC 客户端在千家万户的 NAT 后面,运营商网络不转发组播,移动网络更是连接随时断。行情代理(行情网关、推送网关)就是夹在中间的翻译层:

  • 协议转换:内网组播是私有二进制,公网端换成 TCP 长连接上的私有协议或 WebSocket/Protobuf,适配客户端的弱网环境;
  • 订阅管理:客户端不可能订阅全市场(一部手机的带宽吃不下),代理维护"哪些客户端订了哪些证券",只推订阅内容,这正是单播语义回归的地方——但复制成本从行情服务器转移到了代理层;
  • 流量整形:客户端网络是最大方差来源,代理做合并刷新(同一个证券 200ms 内的多次变动合成一帧推送)、差量压缩、慢客户端检测(写缓冲积压超过阈值就断开让它重连快照同步,而不是让积压无限涨拖垮代理)。

代理层本身是无状态可水平扩展的:不持有行情数据(数据在行情服务器共享内存里,代理只是读者),只持有连接和订阅关系。连接数被打满就加机器,订阅路由用一致性哈希按证券分配到不同代理实例,同一证券的订阅落在同一实例,合并刷新的收益才能吃满。

分层 fan-out 的成本账

完整分发树:交易所 → 专线 → 券商接收机 → 行情服务器(共享内存快照)→ 内网组播 → 行情代理集群 → 公网客户端。每往下一层,单位数据的成本递减、规模递增。行情服务器到代理之间仍可用组播(机房内网),代理到客户端是 N 条 TCP。关键设计原则是有状态的部分收敛在叶子:行情服务器和代理都可以随时重启,靠快照+序列号恢复,任何一层都不允许积累"丢了就补不回来"的状态。

容量估算要在代理层做最坏假设:客户端订阅行为高度同质——涨停板那天,所有人都在看同几只票。按"平均订阅数 × 在线人数 × 峰值行情速率"估代理出口带宽,再留一倍冗余,这是洪峰时代理不崩的生命线。《行情系统的容量与降级》会展开过载时的降级阶梯。

分发树:组播管机房内,代理管公网最后一公里行情服务器共享内存快照区内网组播IGMP 订阅行情代理集群无状态可扩展代理实例 A合并刷新 200ms代理实例 B慢客户端断开1 份仍 1 份到客户端变为 N 条 TCP复制点下移:交换机复制到内网终端,代理复制到公网客户端设计原则:有状态部分收敛在叶子;任一层可重启,靠快照+序列号恢复,不积累不可恢复状态容量最坏假设:涨停日全市场看同几只票,代理出口按 峰值订阅 × 2 冗余 估算