网关层设计:交易所API封装、连接池管理、心跳与重连机制

做市系统里,网关层是什么角色?

说白了,它就是咱们系统和交易所之间的「翻译官」加「快递员」。

交易所那边发过来的行情数据,得靠它拆包、解析、转成咱们内部能用的格式。咱们这边下的订单,也得靠它打包、签名、发出去。

我见过不少团队,一开始觉得网关层就是个网络请求封装,随便写写就行。结果呢?一到行情剧烈波动的时候,连接断了、数据丢了、订单卡住了……嗯,那场面,真是惨不忍睹。

交易所API封装:别让业务代码碰网络细节

我个人习惯,把交易所API封装成三层:

  • 传输层:处理TCP/UDP/WebSocket连接,只管收发字节流
  • 协议层:做序列化/反序列化,比如JSON解析、Protobuf编解码
  • 业务层:提供下单、撤单、查持仓等接口,返回的是咱们内部定义的结构体

为什么要分三层?

你想想看,如果哪天交易所把JSON改成Protobuf了,你只需要改协议层。如果交易所换了IP端口,你只需要改传输层。业务代码?一行都不用动。

我在项目中遇到过一件事:某家交易所突然把WebSocket的ping/pong机制改了。因为我们的封装做得好,只改了传输层几十行代码,整个系统就适配了。隔壁团队没做分层,改了三天,还改出了bug。

核心原则:业务代码永远不要直接操作socket,永远不要直接拼JSON字符串。

连接池管理:别让每次请求都重新握手

做市系统对延迟极其敏感。每次下单都重新建立TCP连接?那延迟至少多出几个毫秒,甚至几十毫秒。在高频场景下,这简直是灾难。

我的做法是:

  1. 系统启动时,预先建立一批连接到交易所
  2. 每个连接分配一个唯一ID,放入连接池
  3. 业务层请求时,从池子里「借」一个连接用
  4. 用完归还,而不是关闭

连接池的大小怎么定?

这得看你的并发量。我一般按这个公式估算:

场景 连接数建议 说明
单品种做市 2-3个 一个主用,一个备用,一个做心跳检测
多品种(10个以内) 每个品种2个 品种间连接隔离,避免互相影响
多品种(10个以上) 品种数×1.5 留出余量,应对突发流量

小技巧:连接池里的连接要定期做「健康检查」。我习惯每隔30秒发一个轻量级的请求(比如查服务器时间),如果连续3次失败,就把这个连接标记为「不可用」,从池子里移除,同时新建一个替补进来。

心跳与重连机制:别让断线变成事故

做市系统最怕什么?

最怕你这边以为连接还活着,实际上交易所那边早就把你踢了。然后你还在傻傻地发单,结果全是废单,甚至因为没收到成交回报,导致仓位管理出问题。

心跳机制,就是用来解决这个问题的。

我一般设计成「双向心跳」:

  • 客户端定时给服务端发ping(比如每5秒一次)
  • 服务端回复pong
  • 如果客户端连续3次没收到pong,判定连接断开
  • 如果服务端连续3次没收到ping,也会主动断开连接

重连机制呢?

嗯,这里要注意:重连不是简单地「断了就重连」。那样会出大问题。

我曾经踩过一个坑:某次交易所网络抖动,我的系统在1秒内重连了50多次。结果交易所把我的IP给临时封了,理由是「疑似攻击」。

从那以后,我设计重连策略时加上了「退避」逻辑:

// 伪代码:带退避的重连策略
int retry_count = 0;
int max_retry = 10;
int base_delay = 1000;  // 初始1秒

while (retry_count < max_retry) {
    bool success = try_connect();
    if (success) {
        retry_count = 0;
        break;
    }
    // 退避:1s, 2s, 4s, 8s, 16s, 32s, 64s...
    int delay = base_delay * (1 << retry_count);
    delay = min(delay, 60000);  // 最大不超过60秒
    sleep(delay);
    retry_count++;
}

警告:重连成功后,一定要做「状态同步」。比如重新订阅行情、重新查询未成交订单、重新同步账户权益。否则你连上去了,但数据是空的,照样没法做交易。

整体架构图

下面这张图,是我做网关层设计时的核心思路。你可以看到,从交易所到业务层,中间经过了哪些环节:

网关层架构图 交易所(行情/交易接口) 传输层(TCP/WebSocket连接管理) 协议层(JSON/Protobuf编解码) 连接池(复用/健康检查) 业务层(下单/撤单/查持仓) 心跳检测 重连退避 状态同步

你看,从下往上,每一层各司其职。传输层只管收发,协议层只管编解码,连接池只管复用和健康检查,业务层只管业务逻辑。这样设计,任何一个环节出问题,都不会波及到其他层。

总结一下:网关层设计,核心就三件事——封装好API、管好连接池、做好心跳和重连。这三件事做好了,你的做市系统就成功了一半。另一半?那是策略和风控的事了。

个人经验:我建议你在开发网关层时,先把「断线模拟」的测试用例写好。比如用iptables模拟网络断开,看看你的重连机制能不能扛住。这个测试,我每次做新系统都会跑一遍,从来没让我失望过。