NDC:从 C 到 Go 的可验证迁移

New Data Collection · 旧系统作为 oracle,迁移结果由真实行为和数据读回决定

项目背景

旧 C Data Collection gateway 长期承担设备 TLS 长连接、状态维护、上行数据和下行控制。系统稳定,但依赖、状态机和扩展成本逐渐增加。目标不是“换语言试试看”,而是在不中断现有系统的前提下,建立一条可验证、可回退的替换路线。

相关系统来自真实工业设备项目,整体经验覆盖约 5.5 万和 1.5 万设备规模。本文的 55k/60k 数据是独立的本地合成 TLS 容量测试,不把它冒充生产流量。

约 1 个月从 Rust 原型推进到 Go 关键行为闭环
80k可重复生成的合成测试设备
60k单轮本地合成 TLS Online 零失败
C / Rust / Go以数据而不是语言偏好做取舍

演进路线

C DC保留长期运行的旧实现,作为协议和外部行为基准。
dc-rs + rpc-go验证协议迁移、Rust 长连接模型和前后端职责拆分。
A/B 验证比较 Rust、Go 与旧 C,验证资源成本、延迟和兼容边界。
dc-go选择团队更易维护的单 binary 路线,逐项追平旧系统。

推进时间线

以旧 C 网关为行为基准,启动 Rust 接入原型,先验证协议解析、TLS 长连接和前后端职责拆分。

形成 dc-rs + rpc-go 路线,Online 与 Upload 开始通过真实客户端和后端读回闭环,而不是只看单元测试。

补齐批量 Online 工具和 Rust/Go A/B。测试表明 Go 尾延迟更好,Rust 内存更低,两者都满足当前连接规模。

主线转向 dc-go,继续追平旧 C 的上线、心跳、上行、下行、超时和依赖恢复等关键外部行为。

当前目标架构

接入与状态

设备或旧客户端通过 TLS 长连接进入 dc-go。网关完成认证兼容、连接所有权、重复上线、超时和断开清理。

后端依赖

PostgreSQL 提供设备与账号数据;Redis 提供在线状态与控制面;Kafka 承载上行数据与通知。

读回验证

dumpdb 从后端链路读取结果。验证不以“网关已写日志”为终点,而以唯一载荷真正读回为终点。

验证工具

dc-debug-client 做单连接和双向 smoke;dc-online-bench 固定压力尺度;rpc-go 保留拆分实验。

文件组织的取舍

dumpdb 的文件布局借鉴了 Git object store 的思路:不把大量对象平铺在单个目录里,而是使用稳定的层级分片规则,把路径本身作为简单索引。

公开示例可抽象为 domain/stream/00/000/0548。这样既避免单目录过大,也保留了文件系统天然的可枚举、可迁移、可人工排查和部分可恢复能力。

这里展示的是文件组织模式,不公开真实业务域、线上 topic、设备标识或生产路径。

已经闭环的行为

55k / 60k 本地合成 TLS Online 对照

以下是最小网关在同机本地合成 TLS Online 场景下的容量验证,不等同于生产网络性能。两种实现均为零失败。

连接数实现p95p99峰值 RSS失败
55,000Rust minimal673 ms1,139 ms约 1.10 GB0
55,000dc-go534 ms690 ms约 1.32 GB0
60,000Rust minimal668 ms995 ms约 1.20 GB0
60,000dc-go572 ms737 ms约 1.57 GB0

这组数据支持了一个务实决策:Go 在该场景拥有更好的尾延迟,Rust 保持明显内存优势;两者都能达到当前连接规模,因此维护成本可以进入决策。

协议细节如何公开

公开材料保留行为契约,不公开字段和报文格式:

我的职责与判断

责任边界:这不是一个人完成的完整云平台。Web service、consumer、API 和部分业务服务由其他工程师负责;这里展示的是我承担的核心设计、关键模块整改、验证路线和技术决策。

客户名称、真实设备编号、生产地址、内部表结构与完整协议字段均未公开。

这项工作的实际变化

返回作品集首页