打开网易新闻 查看精彩图片

一个后端服务,从Rust切到TypeScript,再切回Rust——三次重写,47%的性能波动,团队加班周期从2周变成6周。这不是技术选型失误,是决策链条上每个环节都在埋雷。

第一次:Rust的"安全幻觉"让我们多写了4万行代码

第一次:Rust的"安全幻觉"让我们多写了4万行代码

2022年Q3,团队决定用Rust重写Go写的支付网关。动机很直接:上一季度出了两次内存泄漏,Rust的所有权模型(ownership model)能彻底根治这类问题。

三个月后,代码量从1.2万行膨胀到5.8万行。不是业务变复杂了,是Rust的编译器在逼你显式处理每一个边界情况。一个HTTP请求的参数解析,Go里三行,Rust里要定义结构体、实现反序列化 trait、处理Option嵌套、写单元测试覆盖所有Err分支。

技术负责人李默在复盘会上说:「我们以为买的是安全,结果付的是开发效率。线上bug确实归零了,但新功能上线周期从两周拉到六周。」

更隐蔽的成本在人员端。团队6个人里只有2个有Rust生产经验,另外4个边写边学。一个中级工程师写出的代码, senior要review两轮才能过——不是逻辑问题,是生命周期标注(lifetime annotation)的写法不符合惯用模式。

编译通过只是开始,代码评审才是Rust项目的真实耗时黑洞。

2023年1月,CTO拍板:切到TypeScript,用Node.js跑。理由是「团队人效优先,安全可以用测试补」。

第二次:TypeScript的"类型舒适区"埋了运行时的雷

第二次:TypeScript的"类型舒适区"埋了运行时的雷

迁移比预期快。2个月完成核心模块,代码量压回1.8万行——TypeScript的any类型(any type)在迁移期帮了大忙,先把东西跑起来,类型慢慢补。

问题在半年后暴露。一个支付回调接口,类型定义里声明了amount是number,但上游渠道突然传了字符串"100.00"。TypeScript编译器没报错,运行时直接做了隐式类型转换,结果0.1+0.2的浮点精度问题被放大,对账差了三毛钱。

三毛钱找了一周。日志里看不出问题,因为console.log打印出来是100,进数据库也是100,只有和渠道方原始数据逐笔比对才发现类型漂移。

李默的团队开始疯狂加防御代码:每个外部输入点手动校验,joi/schema-validation 库全量接入。代码量又涨回4.2万行,但这次的冗余不是Rust式的显式处理,是补丁摞补丁的债务累积。

TypeScript的类型系统在编译时给你安全感,运行时该崩还是崩——这层窗户纸,很多团队要踩过坑才捅得破。

性能数据也难看。同样的压测场景,Rust版P99延迟12ms,TypeScript版飙到67ms。不是V8引擎(V8 engine)慢,是单线程事件循环(event loop)里混进了CPU密集型任务,一个JSON大对象的序列化就把后续请求全堵住。

团队试过worker_threads,试过把重计算拆微服务,架构复杂度指数级上升。李默的原话:「Node.js适合IO密集型,我们这是计算密集型场景,硬套就是削足适履。」

第三次:折中方案背后的真实决策逻辑

第三次:折中方案背后的真实决策逻辑

2024年初,团队做了第三次迁移——不是回Rust,是拆服务。

核心支付链路用Rust写,保证延迟和稳定性;运营后台、报表导出用TypeScript,追求迭代速度。中间用gRPC(gRPC远程过程调用协议)通信, schema用Protobuf(Protocol Buffers接口描述语言)锁定,两边各自生成代码。

这个架构的维护成本不低。一个字段变更要改三处:Protobuf定义、Rust端、TypeScript端。但李默算过账:核心链路变更频率是每月1-2次,运营需求是每周3-5次,拆开后各自的人效都回来了。

更意外的收获在团队端。Rust小组缩到2人,专注底层;TypeScript小组4人,快速响应业务。招聘难度直线下降——市场上Rust工程师难找,但愿意写Rust的往往对底层有兴趣,自我驱动力强;TypeScript岗则简历充足。

技术选型不是选最好的,是选能匹配团队结构、业务节奏和招聘市场的。

三次重写的直接成本:14人月,约合当时团队4个月的全部产能。间接成本更难量化——支付网关的稳定性口碑在第二次迁移期间下滑,有两个大客户把结算周期从T+1改成T+3,现金流压力传导到整个公司。

李默现在有个习惯:每次技术评审会,先问「这个决策6个月后能无损回滚吗?」

他的理由是:Rust和TypeScript都是好工具,但工具的价值取决于使用场景和团队状态。第一次选Rust,错在高估了团队的学习带宽;第二次选TypeScript,错在低估了运行时的防御成本;第三次才算把决策框架搭对——先画业务边界,再匹配技术栈,最后看组织能不能跟上。

这个案例在GitHub上有完整的技术文档和压测数据,作者把三次迭代的代码结构、性能曲线、故障记录全开源了。评论区最高赞的反馈是:「看完最大的收获不是Rust或TypeScript该选谁,是意识到我们之前的技术选型会根本没人写决策依据。」

你的团队上一次技术迁移,留下的文档里,有写清楚「当时为什么选这个」吗?