Go服务器性能调优:17年电商实战QPS翻倍路径
|
后台数据不对那一刻,我正盯着QPS曲线发呆——不是陡升,不是崩掉,是平着漂了三分钟,像卡在缓存里出不来的一口气。手机快没电,屏幕右上角剩8%,我顺手按了锁屏,黑下去的瞬间突然想起昨天凌晨三点重启服务时,监控面板上那个被我手动标黄的goroutine堆积数:2173。不是报错,没告警,就那么静静蹲着,跟食堂打饭窗口排到门外的队伍一样合理又刺眼。 我原以为是压测脚本写错了。结果同事小张直接甩来一张截图,是他本地复现跑出来的pprof火焰图,main.main()底下全挤着http.(ServeMux).ServeHTTP,像一串焊死的铁链子——根本没进业务逻辑。我说“你这图太虚”,他回我:“哥,你去看下log中间件里那行debug日志,打出来的时间戳差了400ms。”我愣住,因为那行日志是我上周删掉的,删之前还跟销售老李吐槽:“日志比订单还啰嗦。”老李当时正啃包子,油顺着手指往下滴,头也不抬:“你们后端啊,调参像调相亲对象,怕慢了漏单,又怕快了把钱算错。” 其实问题真不在日志。在中间件嵌套的context.WithTimeout里,超时时间设的是500ms,但上游网关加了120ms固定延迟(他们说是防爬),而我们自己又在gin中间件里套了一层retry-on-503,重试间隔随机在100–300ms之间。三个时间一碰,就像三条不同步的传送带,货没丢,就是永远卡在交接口。烧了不少。不是烧在云服务器账单上,是烧在那几十个反复重建的TCP连接里——每建一次,kernel就得分配socket buffer、time_wait状态堆着不释放,到最后连TIME_WAIT都开始抢端口。平台机制?我看不懂。到底谁管TIME_WAIT回收、谁管tcp_tw_reuse开关、谁管net.ipv4.ip_local_port_range是不是被其他服务偷偷改过?我不问了。问了三次,运维说“线上环境统一配置”,我点个头,心里清楚:统一,就是谁都不敢动。 窗外天黑了,办公室空调太冷,我裹着去年双十一大促时发的冲锋衣坐那儿,突然想起甲方王总上个月说的那句:“你们现在跑得快,但别把系统跑成急诊室。”我当时笑了一下,没接话。急诊室至少还有心跳监护仪,我们这儿连心率波动都靠猜——pprof能抓到CPU热点,但抓不到golang runtime里那层GC暂停时偷偷挪走的几十毫秒;trace能看见调度延迟,但看不出etcd client里的watch连接为什么每小时必断一次;我们连redis pipeline里某次flush阻塞了173ms这事,都得靠业务日志里埋的“start/finish”时间戳倒推。优胜劣汰?对。就是淘汰那些还相信“加机器能解决一切”的人,也淘汰那些以为写完go tool pprof -http=:8080就等于调完了的人。 岔一句:昨天中午跟销售老李去楼下吃刀削面,他边搅面边说,他们最近谈的一个新客户,上线前非要我们签SLA——不是承诺多少QPS,是承诺“99.9%请求延迟低于200ms”。我笑出声,他夹起一筷子面抬头看我:“笑啥?你敢签吗?”我没答。签不了。因为我知道200ms里,有67ms在等MySQL主从同步刷盘,有31ms在等第三方风控接口超时fallback,剩下102ms,才是我们自己写的Go代码真正跑的时间。代码跑得再干净,也扛不住别人家数据库的binlog刷得比我家打印机吐纸还慢。
文章配图,仅供参考 所以一个月前那波QPS翻倍,不是靠换算法、不是换框架、更不是上Service Mesh——是砍掉了两层没意义的middleware,把log middleware从“每个请求打三行”缩成“错误才打一行”,把JWT校验从每次request都验改成只在关键路由验,再把etcd watch的reconnect backoff策略从指数退避改成固定5秒——不是最优,但足够让那一整片goroutine不再堵成早高峰的地铁二号线。封户?没封。但账户健康度评分从73掉到68,后台页面一直在转圈,转了整整两天,直到我把那段panic recover的兜底日志从Info降级成Debug。运维说这样“更符合规范”。我也认了。反正规范从来不说清,为什么规范允许一个recover捕获所有error却偏偏不打印error类型。 不觉得多牛。就感觉像当年第一次用Redis代替MySQL查用户积分——不是技术多高,是终于忍不了那个“查个余额要等800ms”的羞耻感。这次也是。QPS翻倍是结果,不是目标。目标就一个:让老板半夜三点打电话问“订单为啥卡住”时,我能回他一句:“没卡,只是排队,队伍比上个月短一半。”——虽然这话我到现在还没机会说出口。下礼拜准备试下把gorm换成sqlc,不为性能,就为看看能不能让日志里那句“executing query”少出现两次。不行再说。反正Go runtime的GC pause我还是看不懂,下次再骂。 (编辑:站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |




