我用 Rust 重写了 IoT 安全网关的数据面,延迟从 5ms 降到 30μs——CTO 看完压测数据沉默了

15 阅读2分钟

上个月,我们做了一个让团队内部争论了整整一周的决定:把 IoT 安全网关的数据面从 Go 全部重写为 Rust。

不是微调,不是优化,是整个数据面推倒重来。消息传出去后,有朋友问我:“你们团队是不是疯了?Go 写得好好的,为什么要折腾?”

三个月后,压测报告出来的那天,之前反对最激烈的同事在群里发了一句:“我服了。”

为什么换? 我们做的是 IoT-ZTNA 零信任网关,部署在设备和后端之间,所有 IoT 流量必须先经过身份认证、策略校验和行为检测才能放行。

用 Go 写的第一个版本跑得挺稳,直到我们在一个电力客户的真实环境里做 POC——上万台 Modbus 设备同时在线,流量峰值时数据面延迟飙到 5ms,P99 直接冲到 47ms。

客户的 SCADA 系统要求端到端延迟不超过 10ms。5ms 的额外延迟,意味着这套方案直接出局。

问题出在哪?Go 的 GC。每次 GC 停顿 12ms,在高频包处理场景下,这个停顿是致命的。

换 Rust 之后的真实数据 我们用 Rust 的 Tokio + Axum 重写了网关核心,数据面用 Aya 加载 eBPF/XDP 程序,包过滤直接在网卡驱动层完成,根本不走内核网络栈。

相同硬件(4 核 8G 容器)、相同测试工具(wrk)、相同并发(1000 连接):

指标 Go 版本 Rust 版本 提升 吞吐量 31.2K QPS 42.7K QPS +37% P99 延迟 47ms 18ms -62% 内存占用 386MB 142MB -63% GC 停顿 平均 12ms 0 消除 数据面的包处理延迟更是从毫秒级降到了 30μs 以内——因为 XDP 程序在网卡驱动层就完成了 pass/drop 决策,包根本没进入内核协议栈。

不是银弹,但这次值了 Rust 确实有学习曲线。团队里两个写了五年 Go 的工程师,前两周基本在跟 borrow checker 搏斗。

但过了那个坎之后,一切都值了。内存安全由编译器保证,没有 GC 停顿,没有数据竞争的担忧,性能上限高出一大截。

IoT-ZTNA 网关现在已经开源了,核心引擎用 Rust 全栈实现(网关核心、eBPF 数据面、设备 Agent、ONNX 推理、策略评估),唯一的非 Rust 代码是前端 Vue 3。

如果你也在做高性能网络数据面,可以看看我们的实现:

GitHub:suoten/IoT-ZTNA

Gitee:suoten/iot-ztna

Docker 一键启动:docker compose up -d,不需要 Rust 环境。