网关层设计:交易所API封装、连接池管理、心跳与重连机制
做市系统里,网关层是什么角色?
说白了,它就是咱们系统和交易所之间的「翻译官」加「快递员」。
交易所那边发过来的行情数据,得靠它拆包、解析、转成咱们内部能用的格式。咱们这边下的订单,也得靠它打包、签名、发出去。
我见过不少团队,一开始觉得网关层就是个网络请求封装,随便写写就行。结果呢?一到行情剧烈波动的时候,连接断了、数据丢了、订单卡住了……嗯,那场面,真是惨不忍睹。
交易所API封装:别让业务代码碰网络细节
我个人习惯,把交易所API封装成三层:
- 传输层:处理TCP/UDP/WebSocket连接,只管收发字节流
- 协议层:做序列化/反序列化,比如JSON解析、Protobuf编解码
- 业务层:提供下单、撤单、查持仓等接口,返回的是咱们内部定义的结构体
为什么要分三层?
你想想看,如果哪天交易所把JSON改成Protobuf了,你只需要改协议层。如果交易所换了IP端口,你只需要改传输层。业务代码?一行都不用动。
我在项目中遇到过一件事:某家交易所突然把WebSocket的ping/pong机制改了。因为我们的封装做得好,只改了传输层几十行代码,整个系统就适配了。隔壁团队没做分层,改了三天,还改出了bug。
核心原则:业务代码永远不要直接操作socket,永远不要直接拼JSON字符串。
连接池管理:别让每次请求都重新握手
做市系统对延迟极其敏感。每次下单都重新建立TCP连接?那延迟至少多出几个毫秒,甚至几十毫秒。在高频场景下,这简直是灾难。
我的做法是:
- 系统启动时,预先建立一批连接到交易所
- 每个连接分配一个唯一ID,放入连接池
- 业务层请求时,从池子里「借」一个连接用
- 用完归还,而不是关闭
连接池的大小怎么定?
这得看你的并发量。我一般按这个公式估算:
| 场景 | 连接数建议 | 说明 |
|---|---|---|
| 单品种做市 | 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++;
}
警告:重连成功后,一定要做「状态同步」。比如重新订阅行情、重新查询未成交订单、重新同步账户权益。否则你连上去了,但数据是空的,照样没法做交易。
整体架构图
下面这张图,是我做网关层设计时的核心思路。你可以看到,从交易所到业务层,中间经过了哪些环节:
你看,从下往上,每一层各司其职。传输层只管收发,协议层只管编解码,连接池只管复用和健康检查,业务层只管业务逻辑。这样设计,任何一个环节出问题,都不会波及到其他层。
总结一下:网关层设计,核心就三件事——封装好API、管好连接池、做好心跳和重连。这三件事做好了,你的做市系统就成功了一半。另一半?那是策略和风控的事了。
个人经验:我建议你在开发网关层时,先把「断线模拟」的测试用例写好。比如用iptables模拟网络断开,看看你的重连机制能不能扛住。这个测试,我每次做新系统都会跑一遍,从来没让我失望过。