Go服务器性能调优:避坑选型,QPS翻倍实战
|
2025年1月那场压测,我原以为把Go服务器的Pprof调出来就能解决问题,结果被运维小王一句“你CPU采样率设太低了”怼得哑口无言——那天下着雨,机房空调嗡嗡响,我盯着屏幕上的火焰图,发现90%的CPU时间都花在json.Marshal上,可之前明明优化过啊?后来一查,原来是我们用的第三方库在Marshal时偷偷做了反射,而压测工具的采样间隔刚好卡在它的GC周期里,数据全是假的。小王在旁边啃煎饼果子,油渍蹭在键盘上,说“要不试试换fastjson?我上周刚把订单服务的QPS从3k怼到6k”。 换库这事儿,我其实挺抵触的。上季度末我们试过用easyjson,结果因为生成的代码和标准库不兼容,线上出了三次panic——那会儿我正在跟产品经理吵架,他非说“用户反馈登录慢”是我们的问题,我调出日志发现是他的前端埋点代码写了三层嵌套的JSON,把响应包撑大了两倍。扯远了,说回fastjson。我原以为换库得改所有接口,结果发现它跟标准库的API兼容度高达90%,除了Marshal时要加个.Marshaler()的接口实现,其他代码几乎不用动。小王在旁边敲命令行,突然说“哎你看,现在json.Marshal的CPU占比从85%掉到12%了”,我凑过去看,屏幕上的火焰图像被削平了的山,之前那些刺眼的红色块全变成了浅绿色。
文章配图,仅供参考 但QPS没翻倍。压测工具显示只从3.2k涨到4.1k,离预期的6k差得远。我盯着监控面板,发现网络I/O的带宽突然满了——原来我们用的云服务器是1Gbps的,而之前测试时没注意这个限制。小王去茶水间泡面,回来时手里端着碗,汤洒在工位地毯上,说“要不试试把HTTP响应体的Buffer调大?我上次遇到类似问题,把默认的4k改成32k,QPS直接涨了30%”。我试了,确实有效,但只涨到4.8k,还是不够。这时候测试小妹插话:“你们是不是没开HTTP keep-alive?我刚才用Wireshark抓包,发现每个请求都要重新建TCP连接,RTT多了20ms。”她这话让我想起上个月的事——当时我们为了“提升安全性”,强制所有服务关闭了keep-alive,结果线上用户投诉“页面加载超慢”,产品经理差点把我骂哭。我原以为keep-alive只是对长连接有用,没想到在短连接场景下也能省这么多时间。改完配置重启服务,压测工具的数字开始疯涨:5.2k、5.8k、6.1k……最后稳定在6.3k,比优化前翻了一倍。小王把泡面碗扔进垃圾桶,说“早跟你说了,性能调优得先看瓶颈在哪,别一上来就调代码”。我白了他一眼,心想“你刚才不也踩了采样率的坑?”。 但最让我后怕的,是优化过程中差点踩的另一个坑。我们用的ORM框架是gorm,之前为了方便,在模型里嵌套了三层结构体。压测时发现数据库查询时间占了总耗时的40%,我原以为是索引没建好,结果用pprof一看,发现gorm在生成SQL时做了大量的反射和类型断言——尤其是那个嵌套的结构体,每次查询都要递归遍历所有字段,生成一条长达200行的SQL语句。后来我们把模型拆平了,改成用原始SQL拼接,查询时间直接从120ms降到30ms。小王在旁边补刀:“我早说过gorm不适合高并发,你们非要用,现在知道疼了吧?”我懒得理他,心想“至少我们没像某些团队那样,为了用ORM把所有查询都写成链式调用,结果生成一堆低效的SQL”。 现在回头看,这次优化能成功,其实就靠三个字:优胜劣汰。我们试了四个JSON库,最后选了fastjson;改了三次HTTP配置,才找到keep-alive这个关键;拆了两版模型,才把gorm的反射开销干掉。每一步都踩过坑,但每一步也都排除了一个错误选项。小王说“性能调优就像打游戏,得先找到BOSS的弱点,再集中火力打”,我觉得挺对——但下次能不能别在我吃午饭的时候说这种话?刚才的煎饼果子味儿还粘在键盘上呢。 对了,我们优化完第二天,云厂商的销售找上门,说“你们现在QPS这么高,要不要升级到10Gbps的带宽?我们最近有优惠”。我盯着他递来的合同,心想“这算不算另一种形式的优胜劣汰?”。 (编辑:站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |


