一动就扩容,扩了就不缩第一枪打错了地方三个偏方,全都不对劲真相:GC 眼里,内存管够一行配置,当场痊愈这单交的学费
先说结论:这次折腾了好几天的内存问题,最后发现连 bug 都算不上——是部署文件里少写了一行配置。
事情是这样的。我们有个海外项目,一共 70 个服务,前前后后花了一年多时间才完成云服务迁移和架构调整:容器从 docker swarm 换成 Kubernetes,托管在 AWS 的 EKS 上。单个服务本身没怎么动,但外围架构整个换了血。
新架构上线,内存问题就跟着来了。挑一个最典型的服务说:一个普通的 ASP.NET Core gRPC 工程,平时流量不大,但它的内存曲线,怎么看怎么不对劲。
这个服务在 K8s 里配了自动扩缩容(HPA),内存请求值(request)设的 512Mi,最大副本数 5。结果生产环境一启动,Pod 内存蹭一下顶到 512Mi,直接触发扩容,5 个副本拉满。
![]()
HPA 拉满 5 个副本,每个 Pod 内存都在 500Mi 上下
更邪门的是两点:
- • 副本内存长时间维持在 500~600Mi 不释放,压测的时候甚至能冲到 800Mi;
- • 就算完全没有请求,内存也要超过 20 个小时才慢慢降到 350Mi 左右;
- • 而接口响应时间完全正常,用户毫无感知。
QA 环境压根没这毛病,所以测试阶段一点征兆都没有。老板看曲线血压升高,我们只能自己上手查。
排查的第一反应永远是:是不是代码有内存泄漏?毕竟其他类似服务都好好的。
于是开始翻代码。翻了好几遍,除了几处 ToList 用得太频繁,没发现问题;用 VS 诊断工具跑了一遍,也没有内存泄露。不死心,又在 QA 环境用 dotnet-dump 把内存快照拉下来分析,还真找到一个大对象堆(LOH)驻留的类型——一个从数据库查列表再分组计算的类。
然后开始最原始的二分法+注释大法:把这个查询注释掉,内存果然只在 300Mi 左右,回落也变快了。眼看就要结案,结果继续往下拆——最后只保留数据库查询、连返回值引用都不接,内存照样冲到 500~600Mi。
这就离谱了。列表拢共才 11000 条数据,一个查询而已,怎么就能把内存顶穿扩容线?代码这条路,走到头了。
代码查不出毛病,那就调 GC。先后试了三个方案:
![]()
![]()
定时执行 GC.Collect 的实验:蓝色 Pod 每 5 分钟回收一次,内存确实压下来了
看起来方案一、三都能用,但查了资料心里更虚了:ASP.NET Core 默认就是 Server GC,为高性能设计,本来就不会频繁回收。强行换模式、强行手动回收,都是跟框架拧着干。真正的病根,不在这。
查资料的过程中才反应过来一个被忽略的基本设定:K8s 的容器资源有request(预留)和limit(上限)两套值。我们的部署文件只写了 request,没写 limit。
这意味着什么?得让 GC 自己说话。于是给服务加了个查询接口:
![]()
一查,答案直接糊脸上——
![]()
GC 感知到的可用内存:4,037,939,200 字节,约 4Gi
GC 眼里的可用内存是4Gi——因为没设 limit,容器直接把宿主机的 4GB 内存当成了自己的额度。对 GC 来说,内存管够,凭什么急着回收?所以它慢悠悠地攒着,攒到触发 HPA 阈值,副本一个个拉满,内存曲线自然死活不降。
补上 limit:
![]()
加上 limit 后再查,可用内存变成 512Mi。重新压测:
![]()
修复后:压测结束内存回落,副本缩容正常
内存释放正常,副本扩了能缩、缩了能稳,接口响应时间没受任何影响。折腾了好几天的问题,收工只用了一行配置。
- • 遇到内存居高不下,先别急着怀疑代码——先确认 .NET 的 GC 模式(Server 还是 Workstation),再确认容器实际分到的可用内存是多少;
- • K8s 下第一件事就是检查资源 limit 有没有设置,没有 limit,GC 会把宿主机内存当成自己的额度;
- • limit 设了还有泄漏,再去翻代码也不迟。
说白了,这次不是代码写错了,是「环境」和「预期」根本没对上:你以为容器只有 512Mi,GC 以为它有 4Gi。两边各说各话,内存曲线就成了悬案。
你的项目里,request 和 limit 都配齐了吗?评论区聊聊,我猜不少人只写了 request
特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。
Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.