加入收藏 | 设为首页 | 会员中心 | 我要投稿 站长网 (https://www.023zz.com.cn/)- 高性能计算、物联设备、数据可视化、操作系统、基础存储!
当前位置: 首页 > 服务器 > 系统 > 正文

Go服务器性能调优:避坑选型,QPS翻倍实战

发布时间:2026-10-29 08:07:52 所属栏目:系统 来源:DaWei
导读:  去年十二月份,凌晨三点二十,机房空调坏了半边,嗡嗡声像有人拿螺丝刀在刮机柜背面——就那个老机柜,编号C7,散热孔常年堵着灰毛,我上次擦它还是上个月搬家时顺手干的。当时我正蹲在机柜前扒拉日志,左手捏着泡面叉子,右手摸

  去年十二月份,凌晨三点二十,机房空调坏了半边,嗡嗡声像有人拿螺丝刀在刮机柜背面——就那个老机柜,编号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,中间夹着\
\
\
\
没对齐。它们断了,QPS反而从1800蹦到3600。我盯了四十来分钟,不是看数字,是看pprof火焰图里runtime.mallocgc那一坨是不是还在乱跳。它不跳了。但CPU使用率没降——平移了,从user态挪到了sys态,syscall.syscall占满一个核。我又切过去看/proc/pid/status,Threads列从128飙到407,线程池炸了。这时候值班室门口探进个头,是我们组新人小陈,手里拎着保温杯,说“哥,老板刚在大群@你,问‘到底是不是Go的问题’”。我没回,低头抠掉监控屏胶布边缘翘起的一角,露出底下“2023-05-12 故障复盘会”几个字,笔迹是老张写的,他现在在隔壁做架构师,再也不碰生产环境。


文章配图,仅供参考

  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数量。别的,等天亮再说。

(编辑:站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!