三年前,我们团队把核心支付服务从HTTP/1.1迁移到gRPC,期待性能提升。结果上线72小时后,Go写的gRPC服务内存暴涨847%,差点把生产环境拖垮。这不是故事,是账单上的数字。
当时我们做了常规基准测试,Go的并发表现很漂亮,延迟数据也好看。但生产环境的并发模式和测试工具完全不同——大量短连接、突发流量、不规则的请求分布。这些才是真相的试金石。
打开网易新闻 查看精彩图片
六个月后,我们带着教训重新设计测试。对比对象是两个主流实现:Rust的tonic库,和Google官方维护的grpc-go。测试维度只有一个标准:生产环境真正在乎的指标。
先说结论,和网上流传的说法相反。grpc-go的吞吐量确实高,在CPU充足、内存管够的场景下跑得飞快。但tonic在1 CPU限制的容器环境里,延迟和内存占用都更优。如果你的服务要水平扩展,每台机器塞几十个实例,这个差距会被放大几十倍。
问题出在Go的垃圾回收。基准测试里请求量少,GC压力不明显。生产负载一上来,内存分配频率飙升,STW(Stop-The-World)停顿累积,尾延迟直接爆炸。Rust没有GC,内存布局紧凑,同样的流量下RSS(常驻内存)只有Go的1/8到1/6。
但tonic也不是万能药。Rust的学习曲线陡峭,编译时间长,生态工具链不如Go成熟。团队里没有Rust经验的话,维护成本会吃掉性能收益。我们最后的选择是混合架构:对延迟敏感的计费服务用tonic,内部管理后台继续grpc-go。
这次踩坑教会我们一件事:性能测试必须复制生产条件,否则数字就是幻觉。那些"Go gRPC性能最好"的博客文章,大多没跑过真实负载。
热门跟贴