Go服务器性能调优:避坑选型,QPS翻倍实战
|
去年十二月份,凌晨三点二十,机房空调坏了半边,嗡嗡声像有人拿螺丝刀在刮机柜背面——就那个老机柜,编号C7,散热孔常年堵着灰毛,我上次擦它还是上个月搬家时顺手干的。当时我正蹲在机柜前扒拉日志,左手捏着泡面叉子,右手摸到SSD温度报警灯亮了第三颗红灯,烫手。 监控屏右下角贴着块蓝胶布,遮着去年五月被咖啡泼过的裂痕。我盯着它看了三秒,突然想起来——上回搬家,搬家公司把我的三块NVMe全塞进泡沫箱底层,最底下那块压出两道印子,回来一跑fio,latency直接飘到12ms。可当时没人信,说“Go不压磁盘”,我说“你试试往etcd里塞一百万键再删一半”,那人当场掏手机查golang.org/doc/go1.19……结果查到一半,他孩子打来电话问“爸爸你今晚回不回来吃饺子”,他直接挂了。 所以这次我真没碰磁盘——真没碰。我改的是http.Server的ReadTimeout和WriteTimeout,调成30秒。因为上周五客户那边报了个“偶发504”,运维甩锅给CDN,CDN甩锅给我们的TLS握手慢。可我看Wireshark抓包,三次握手正常,SYN-ACK响应毫秒级,但第一个HTTP request卡在Client Hello之后整整四十七秒。我原以为是证书链问题,结果发现是客户端根本没发Client Hello——它在等我们发完Server Hello后、Certificate之前那帧“Hello Retry Request”。而Go 1.18默认关着这个逻辑,除非你显式配tls.Config.CipherSuites带入TLS_AES_128_GCM_SHA256,否则遇到某些安卓旧内核,握手就僵在那儿,不超时、不重传、不报错,就晾着。服务器端socket还挂着,fd不释放,连接数悄悄堆到八千多。我凌晨两点翻完net/http源码,在$GOROOT/src/net/http/server.go第3211行看见那行注释:“// TODO: consider enforcing idle timeout during TLS handshake”——它写了三年了,还没动。 然后我动了ReadHeaderTimeout,改成五秒。立刻有十四个连接断掉,全是Java客户端,header写得松垮,User-Agent里混着emoji,中间夹着\
文章配图,仅供参考 DNS解析没崩,证书没过期,带宽只用了六成七,主从同步延迟恒定在23ms——全都没事。就一个东西塌了:conn.SetDeadline()。Go标准库里所有net.Conn方法都走它,包括http.Transport的底层DialContext,而deadline背后是epoll_ctl加EPOLLONESHOT的封装,一旦设错时间单位,就可能触发Linux内核229号补丁的竞态——具体哪个字段?我现在也说不准。只知道把time.Second 30换成30 time.Second之后,同一台机器压测,P99延迟曲线从锯齿变成直线。这事儿我跟运维李姐吵过,她非说“参数顺序哪能影响性能”,结果我俩拿perf record -e syscalls:sys_enter_setsockopt -p $PID 对比,她自己数出来,错位那个参数让setsockopt进了两次系统调用,每次差0.3毫秒,但十万并发叠起来……她没数完,手机响了,是孩子老师问作业,她把耳机一摘,转身去泡枸杞茶了。 窗外雨没停,顺着玻璃往下淌,把远处路灯晕成黄团。我忽然想起上个月在西安中转,高铁站便利店买水,扫码付钱时APP卡在“请稍候”三秒,旁边卖票大叔咧嘴一笑:“小伙子,你这手机怕是装太多App了吧?”我点头,他递过一瓶冰水,瓶身全是水珠,凉得扎手。那一刻我觉得他说得对。Go服务也是,装太多“默认配置”、“最佳实践”、“兼容性兜底”,结果连一次TCP连接都不让你好好关掉。 优胜劣汰不是选谁赢,是淘汰那些明明能设超时却写0的代码,淘汰那些把log.Printf当panic的函数,淘汰那些认为“不报panic就是稳定”的人。我不信什么高可用,我就信——conn.Close()之后,fd真归零了没?netstat -an | grep :8080里,TIME_WAIT是不是还在爬?这些数字不会骗人,骗人的都是人嘴里跑出来的词儿。比如“这个我们早就适配好了”,比如“客户那边反馈很平稳”,比如“应该不是我们的问题”。 小陈又来了,站门口不动,手里保温杯换了只新杯子,杯盖上印着“2024年度进步员工”。他清清嗓子:“哥,监控群里刚刷屏,新上线那个灰度节点,QPS冲到三千九百,P95掉到38毫秒。”我嗯了一声,伸手摸了摸C7机柜侧板——不烫了。但指尖沾了层灰,抹在裤子上留了道白印。我起身把泡面桶塞进脚边塑料袋,里面还有半盒没拆的湿纸巾,包装上写着“无酒精配方”,日期是十一月二十三日。明天先把告警阈值调了,不按QPS调,按Threads数量。别的,等天亮再说。 (编辑:站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |


VR开发编译优化与性能调优实战指南
