一、从OSI七层模型说起
做网络协议这么多年,我经常被问到同一个问题:「为什么交易所不用标准的TCP/IP协议栈?」
要回答这个问题,得先聊聊OSI七层模型。说实话,这玩意儿在教科书里被神化了。实际工程中,没人会严格按照七层去实现。但它的分层思想,确实帮我们理解网络通信提供了很好的框架。
OSI七层模型长这样:
| 层级 | 名称 | 典型协议 | 一句话理解 |
|---|---|---|---|
| 7 | 应用层 | HTTP、FIX | 业务数据长什么样 |
| 6 | 表示层 | SSL/TLS | 数据要不要加密压缩 |
| 5 | 会话层 | NetBIOS | 谁跟谁在说话 |
| 4 | 传输层 | TCP、UDP | 数据怎么可靠到达 |
| 3 | 网络层 | IP | 数据走哪条路 |
| 2 | 数据链路层 | 以太网 | 相邻设备怎么传 |
| 1 | 物理层 | 光纤、双绞线 | 比特流怎么变成电信号 |
嗯,这张表大家应该都见过。但我想说的是——交易所根本不关心第5、6层。为什么?往下看。
二、交易所协议栈的「瘦身」哲学
我2015年参与过一个期货交易所的协议改造项目。当时客户要求:从下单到收到成交确认,延迟不能超过10微秒。你想想看,标准TCP协议栈光握手就要一个RTT(往返时间),在千兆网络下也得几十微秒。这还没算上业务处理时间。
所以交易所的协议栈,说白了就是「能砍的全砍掉」。
2.1 砍掉会话层和表示层
交易所不需要会话管理?错,需要。但它的会话管理极其简单——一条TCP连接就是一个会话。不需要复杂的建立、维护、拆除流程。表示层?交易所的数据格式是固定的,不需要内容协商。你见过哪个交易所的行情数据还用XML传?那延迟得吓死人。
2.2 传输层:TCP还是UDP?
这是个经典问题。我个人的经验是:
- 交易指令(下单、撤单):必须用TCP。为什么?因为指令不能丢。你想想看,一个撤单指令丢了,可能造成几百万的损失。我在项目中遇到过,某次因为UDP丢包导致撤单失败,客户差点起诉我们。
- 行情数据:用UDP。行情是广播式的,丢一帧无所谓,下一帧马上就来。如果用TCP重传,反而会造成延迟堆积。
核心原则:交易所协议栈的设计,本质上是「在确定性延迟和可靠性之间做取舍」。交易指令要可靠,行情数据要快。
三、交易所专用协议栈长什么样?
我画了一张图,帮你理解交易所协议栈的典型架构:
这张图你看懂了吗?交易所的协议栈,其实就是在标准OSI模型上做了两件事:砍掉冗余层,加速关键层。
四、为什么交易所需要定制化协议?
这个问题,我用三个关键词来回答:延迟、确定性、吞吐量。
4.1 延迟:微秒级的生死时速
你可能听说过「纳秒级交易」这个词。嗯,那是高频交易(HFT)的世界。在交易所内部,从行情数据到达,到交易引擎做出响应,再到订单发往撮合系统,整个链路的时间预算通常只有几十微秒。
标准TCP协议栈在这点上完全不合格。我举个例子:
- TCP的Nagle算法会合并小包,增加延迟
- TCP的拥塞控制会在丢包时降低发送速率
- TCP的头部开销(20字节)在短报文场景下占比过高
交易所的解决方案是什么?直接绕过操作系统内核协议栈。用DPDK、RDMA等技术,让应用程序直接操作网卡。我曾经在一个项目中,把数据从网卡到应用层的延迟从50微秒降到了5微秒。怎么做到的?说白了就是「不走寻常路」——绕过内核,直接内存映射。
4.2 确定性:不能有「意外」
交易所最怕什么?不是慢,是「忽快忽慢」。你想想看,如果行情数据有时1微秒到,有时100微秒到,交易策略怎么设计?
标准TCP协议栈的延迟抖动很大。为什么?因为内核要处理中断、调度、内存拷贝。这些操作的时间是不确定的。交易所需要的是「硬实时」——每个数据包的处理时间都是可预测的。
避坑指南:我曾经在一个项目中,用标准Linux内核跑交易系统。结果发现,当系统负载高时,网络延迟会突然飙升到毫秒级。排查了半天,发现是内核的软中断处理在CPU之间迁移导致的。后来我们绑定了CPU核心,才解决了这个问题。
4.3 吞吐量:百万级订单的挑战
国内头部交易所,峰值时每秒要处理几十万笔订单。每笔订单虽然只有几十字节,但加上协议头、ACK确认、重传机制,网络开销会急剧膨胀。
交易所的定制化协议,通常采用以下手段:
- 批量处理:多个订单打包在一个网络包中发送
- 精简头部:自定义协议头,可能只有4-8字节
- 零拷贝:数据从网卡直接到应用内存,不经过内核缓冲区
我见过最极端的例子,某交易所的自定义协议,一个UDP包塞了1000笔订单。头部只有6个字节:2字节序列号 + 2字节长度 + 2字节校验。相比TCP的20字节头部,节省了70%的开销。
五、一个具体的例子:FIX协议 vs 交易所专用协议
FIX(金融信息交换)协议是金融行业的通用标准。但说实话,它在交易所场景下太「重」了。
看一个FIX下单消息的例子:
8=FIX.4.2|9=78|35=D|49=CLIENT1|56=EXCHANGE|34=1|52=20240101-00:00:00|11=ORDER001|55=600519|54=1|38=100|44=200.50|40=2|10=123|
这条消息有200多字节。其中大部分是标签(如8=、9=)和分隔符(|)。对于交易所来说,这些冗余信息完全可以去掉。
交易所的专用协议可能长这样:
0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x0A 0x0B 0x0C
嗯,只有12个字节。每个字节代表一个字段,位置固定,不需要标签。解析速度极快——直接内存拷贝,不需要字符串解析。
注意:这种极简协议虽然快,但可读性极差。调试时得用专门的抓包工具。我建议在开发阶段保留一份FIX协议的日志,方便排查问题。上线后再切到专用协议。
六、总结:定制化协议的核心思路
说了这么多,其实就一句话:交易所的协议栈,是「用确定性换性能」的极致工程实践。
标准协议栈追求通用性,什么场景都能用。交易所协议栈追求极致性能,只做一件事——在微秒级时间内,可靠地传输交易数据。
如果你要设计一个交易所协议栈,记住这三点:
- 砍掉不需要的层:会话管理、内容协商,能省则省
- 优化传输层:TCP调参,UDP+FEC(前向纠错),或者直接上RDMA
- 硬件加速:FPGA、ASIC、智能网卡,能上就上
最后说一句:不要迷信标准协议。在交易所这个领域,每微秒的延迟都意味着真金白银。定制化不是炫技,是生存需要。
公众号:蓝海资料掘金营,微信deep3321