第4章:网络协议栈:从TCP到UDP,再到RDMA与用户态协议栈的演进
做高频交易这些年,我最大的感触就是——网络协议栈的选择,直接决定了你的交易延迟是微秒级还是毫秒级。说白了,这就是一场与操作系统内核的博弈。
今天咱们聊聊协议栈的演进之路。这条路我走了十几年,踩过的坑不少,但收获也很大。
4.1 TCP:稳定但慢,为什么?
TCP 是互联网的基石。可靠、有序、流量控制,这些特性让它成为通用场景的首选。
但在高频交易里,TCP 有个致命问题——延迟太高。
为什么会这样?我拆开给你看:
- 三次握手:每次建立连接都要来回一次,1个RTT就没了
- 拥塞控制:慢启动、拥塞避免,这些算法在交易网络里完全是累赘
- ACK确认机制:每个包都要等确认,浪费带宽也浪费时间
- 内核态开销:每次收发数据都要陷入内核,上下文切换的成本很高
核心问题:TCP 的设计目标是公平和可靠,而不是低延迟。在高频交易这种“确定性优先”的场景里,TCP 的很多机制反而成了负担。
我记得有一次,帮一家做市商优化交易链路。他们用的是标准 TCP,订单从生成到到达交易所,平均延迟是 120 微秒。我们换成 UDP 后,直接降到了 25 微秒。你想想看,这差距有多大。
4.2 UDP:轻量但不可靠,怎么用?
UDP 没有握手、没有拥塞控制、没有重传。它就是个“发出去就不管”的协议。
但正因为简单,它才快。
在高频交易里,UDP 的典型用法是:
- 行情数据推送:丢几个包没关系,下一笔马上就到
- 订单发送:在应用层自己做重传和校验
- 时间同步:PTP 协议就是基于 UDP 的
不过,UDP 也不是银弹。我遇到过一个问题:UDP 没有流量控制,如果发送端太快,接收端的缓冲区会溢出,导致丢包。嗯,这里要注意——在高频场景下,丢包率哪怕只有 0.1%,也可能导致策略失效。
我的建议:用 UDP 时,一定要在应用层实现简单的确认和重传机制。别指望内核帮你擦屁股。
4.3 RDMA:绕过内核,直击硬件
RDMA(Remote Direct Memory Access)是真正的“降维打击”。它允许一台机器的应用直接读写另一台机器的内存,完全绕过操作系统内核。
我最早接触 RDMA 是在 2015 年,当时帮一家量化基金搭建交易系统。他们从纽约到芝加哥的链路,用 TCP 延迟是 7.3 毫秒,换成 RDMA 后降到了 3.8 毫秒。几乎砍了一半。
RDMA 的核心优势:
- 零拷贝:数据直接从网卡到应用内存,不需要经过内核缓冲区
- 内核旁路:不需要系统调用,省去了上下文切换
- CPU卸载:数据传输由网卡硬件完成,CPU 可以专心做计算
RDMA 有两种主流实现:
| 特性 | InfiniBand | RoCEv2 |
|---|---|---|
| 延迟 | 极低(<1μs) | 低(1-3μs) |
| 成本 | 高(专用硬件) | 中等(以太网+RDMA网卡) |
| 兼容性 | 需要专用交换机 | 兼容标准以太网 |
| 部署难度 | 高 | 中等 |
避坑指南:我曾经在 RoCEv2 上踩过一个坑——PFC(优先级流控)配置不当,导致整个网络出现死锁。后来花了整整两周才定位到问题。所以,用 RDMA 之前,一定要先做充分的网络调优。
4.4 用户态协议栈:终极武器
如果说 RDMA 是绕过内核,那用户态协议栈就是“自己造轮子”。
什么意思?就是把整个 TCP/IP 协议栈搬到用户空间,完全由应用控制。这样做的优势很明显:
- 零系统调用:所有操作都在用户态完成
- 自定义协议:可以去掉不需要的头部字段,减少包大小
- 确定性延迟:没有内核调度干扰,延迟更稳定
常见的用户态协议栈方案:
- DPDK:Intel 出品,最流行的用户态网络框架
- Solarflare OpenOnload:专为金融交易设计的协议栈
- Mellanox VMA:配合 Mellanox 网卡使用,延迟极低
下面是一个简单的 DPDK 接收数据包的示例:
// DPDK 接收数据包示例
static void lcore_recv_packets(void) {
struct rte_mbuf *bufs[BURST_SIZE];
uint16_t nb_rx;
while (1) {
// 从网卡接收一批数据包
nb_rx = rte_eth_rx_burst(port_id, 0, bufs, BURST_SIZE);
if (unlikely(nb_rx == 0))
continue;
// 处理每个数据包
for (int i = 0; i < nb_rx; i++) {
process_packet(bufs[i]);
rte_pktmbuf_free(bufs[i]);
}
}
}
这段代码看起来简单,但背后涉及的东西很多。比如内存池管理、NUMA 亲和性、CPU 隔离等等。我刚开始用 DPDK 时,光是调优内存分配就花了一周。
关键点:用户态协议栈不是万能的。它需要应用层自己处理 TCP 的可靠性、重传、流量控制等逻辑。开发成本很高,但延迟收益也很可观。
4.5 协议栈选择决策树
说了这么多,到底该怎么选?我画了一张图,帮你理清思路:
4.6 实战经验总结
做了这么多年高频交易网络,我总结了几条经验:
- 不要迷信某个协议。TCP 有 TCP 的适用场景,UDP 有 UDP 的局限。关键是看你的业务需求。
- 延迟和吞吐量要分开看。高频交易更关注延迟,尤其是尾部延迟(99.9%分位)。
- 硬件加速是趋势。不管是 RDMA 还是 DPDK,都在把工作从 CPU 卸载到网卡上。
- 测试环境要贴近生产。我见过太多人在实验室里测出 1μs 延迟,上线后变成 10μs。网络抖动、交换机缓存、光纤长度,这些都会影响实际表现。
我的习惯:每次做协议栈选型时,我都会先跑一个简单的 ping-pong 测试,看看基础延迟。然后再加负载,看延迟分布。最后才决定用哪个方案。
好了,这一章就聊到这里。协议栈的选择没有标准答案,但理解了 TCP、UDP、RDMA 和用户态协议栈的优缺点,你就能根据实际情况做出最优决策。
公众号:蓝海资料掘金营,微信deep3321