已采纳
回答正文
回复
讨论正文
该问题的正文与回答。
Go 1.22.7 无状态订单查询 API,K8s 部署(K8s 1.28.9 / containerd 1.7.13 / cgroup v2 / 内核 5.15.0-91),Pod spec memory.request=4Gi / memory.limit=4Gi(request=limit 避免 QoS 降级),节点 16C64G。单实例 goroutine 稳在 1500~2000,QPS 约 6000,主要开销在 JSON 编解码 + MySQL 查询(database/sql + go-sql-driver/mysql,MaxOpenConns=200)。
目前 GOGC 用默认 100,没设 GOMEMLIMIT。
GODEBUG=gctrace=1 日志里能看到 assist 时间从 2ms 涨到 30~80ms,t=xxx s gc N @X.XXMB X% Xms Y% 中 X%(GC 占比)从 5%~8% 爬到 12%~15%;go tool pprof http://localhost:6060/debug/pprof/profile?seconds=60:CPU profile 里 GC assist 占比约 15%~22%,top 分配热点是 JSON 编解码(encoding/json Marshal/Unmarshal)和 map 扩容;GODEBUG=gctrace=1:确认 assist 在恶化(如上),不是 STW 本身变长(STW 基本稳定在 0.3~1.2ms);GOGC=200:P99 毛刺频率降了一半(约 3~4 分钟一次),但 HeapAlloc 峰值涨到 3.2Gi,离 limit 只剩 800Mi,不敢再调大;GOMEMLIMIT=3500Mi(GOGC 保持 100):效果不明显,assist 还是 20~60ms,不确定 GOMEMLIMIT 到底有没有生效。testing.B + benchstat 或自写压测脚本)能把 GC 调参的效果隔离出来?jsoniter / encoding/v2 / 预分配 buffer)?社区里有没有人实测过替换 encoding/json 后 GC assist 的改善幅度?社区里已有《Go 服务 p99 间歇性 GC 毛刺:GOGC 调大 vs heap ballast vs 代码侧少分配,线上到底怎么选?》(id=683) 讨论过 GOGC vs ballast vs 少分配的选择,以及《Go 服务 limit=4Gi 却 OOMKilled:GOMEMLIMIT 是软提示》(id=2250) 讲过 GOMEMLIMIT 的内存预算。我的场景更具体:assist 在恶化、毛刺频率在加速,这暗示分配速率可能超过了 GC 的吞吐能力,单纯调大 GOGC 可能只是把堆撑大而不是解决根因。想看看大家有没有针对「assist 恶化 + 毛刺加速」这个组合的实战经验。