ICP备案

备案站点的内存泄漏与 OOM 排查

作者:备案源头内容团队内容审核:备案源头内容团队更新于 2026年9月15日

进程「莫名其妙」消失,多半是被杀的

这类故障有个共同特征:应用日志里什么都没有,最后一行是正常的业务日志,然后进程就没了。既没有异常堆栈,也没有关闭日志。原因通常不在应用内部——是内核的 OOM Killer 或容器的内存限制直接发了 SIGKILL,进程根本没有机会写下遗言。

关键要点

  • 先分清三种情况:应用内存泄漏、容器内存上限被打爆、宿主机内存耗尽误杀无辜进程,处理方式完全不同。
  • 堆平稳但进程内存持续上涨,说明问题在堆外,查线程数、连接缓冲和 native 内存。
  • OOM 之后第一件事是取证而不是重启,重启会抹掉现场。
  • 容器里的内存上限不等于运行时自己看到的上限,必须显式配置。

三种「内存不够」的区分

现象 关键线索 方向
进程无日志突然消失 系统日志里有 oom-kill 记录 宿主机内存耗尽,内核选中了它
容器反复重启,退出码 137 容器内存上限 超出 limit 被强杀
不退出但延迟抖动、GC 频繁 GC 耗时占比上升 堆内泄漏或堆配小了
进程内存持续涨、堆很平稳 RSS 与堆的差值变大 堆外内存(线程、缓冲、native)

注意第一种的陷阱:内核挑选的不一定是罪魁,它倾向于杀占用最大的进程。数据库被杀了,真正泄漏的可能是旁边那个应用。

先判断:是泄漏,还是容量不够

两者的曲线形态完全不同:

  • 泄漏:重启后从低位开始单调爬升,与流量涨跌关系不大,跌不回来。
  • 容量不足:随流量波动,峰值顶到上限但低峰会回落。

观察窗口至少覆盖一个完整业务周期(含低峰)。只看几十分钟的曲线,两者长得一模一样。容量侧的评估方法见 容量规划与弹性伸缩

重启前必须抓的四项现场

  1. 系统日志:确认是否发生 oom-kill、被杀的是哪个进程、当时的内存水位。
  2. 指标曲线:进程内存、堆使用、GC 次数与耗时、线程数,见 可观测性建设
  3. 内存快照:导出堆快照或内存剖析文件;导出会造成停顿,先把这台实例从负载均衡摘掉再做。
  4. 句柄与连接:打开的文件数、网络连接数、线程数——它们本身常常就是泄漏源。

抓完再重启止血。跳过取证的代价是:下一次同样的故障你依然只能重启。排障所需的日志字段规范见 日志规范与集中检索

六种常见泄漏模式

模式 典型写法 修法
无界本地缓存 用哈希表当缓存,不设上限与过期 改用带容量上限和过期的缓存,或外置,见 缓存与 Redis 运维
监听器/回调未注销 注册了从不解绑 成对注册与注销
线程池无界队列 任务堆积撑爆内存 有界队列 + 拒绝策略,见 消息队列与异步任务运维
连接或流未关闭 异常路径漏了释放 统一用带自动释放的语法;连接侧见 数据库连接池与连接数治理
上下文持有大对象 请求上下文里塞完整响应体 只留必要字段
全局集合只增不删 静态注册表、去重集合 加过期或容量上限

排查时的一个实用技巧:对比两次内存快照的差异,看哪类对象数量在持续增长,通常一眼就能看出是哪种模式。

容器环境的两个专属坑

运行时看不到容器限制:部分运行时默认按宿主机物理内存推算自己的内存上限。宿主机 32G、容器 limit 2G,运行时却以为自己有 32G 可用,于是稳定地在堆涨到 2G 时被强杀。解法是显式配置内存/堆上限,或开启感知容器限制的选项,容器部署要点见 容器化部署要点

退出码要分清:137 表示被 SIGKILL(多为超出内存限制),143 表示收到 SIGTERM 正常退出。看到 143 应该去查发布或调度,而不是查内存,优雅停机的处理见 优雅停机与健康检查

堆外内存:RSS 涨而堆不涨

这种情况排查方向不在业务代码里,而在这几处:线程数暴涨(每个线程都有独立栈)、native 库分配的内存、压缩与加解密的缓冲区、内存映射文件、连接的读写缓冲。先看线程数与连接数曲线,它们是最容易定位的两个入口,也是最常见的元凶。

止血与根治的边界

止血手段(临时):限流降低并发(见 限流、熔断与服务降级)、临时调大内存上限换排查时间、滚动重启。

根治:修掉泄漏点,并补上基于增长率的告警——「内存 24 小时内单调上涨且不回落」比「内存超过 90%」发现得早得多,告警落地见 备案网站监控告警体系。事后复盘与改进项跟踪见 故障响应、复盘与 SLO 实践

定时重启可以作为过渡,但必须写进台账并挂上到期复查,否则它会变成永久方案——直到某天重启间隔也扛不住。

常见坑

  • 出事先重启:现场全毁,下次继续猜。
  • 只盯堆不看进程内存:堆外泄漏完全看不见。
  • 容器上限与运行时堆没对齐:稳定被 137 杀,还以为是代码问题。
  • 把定时重启当解决方案:泄漏速度变快时会突然失效。
  • 只设绝对阈值告警:到 90% 时 GC 已经抖了很久,用户早有感知。

常见问题

怎么快速判断是内存泄漏还是内存不够?

看重启后的曲线形态:泄漏是与流量无关的单调爬升且不回落;容量不足是随流量波动、低峰能回落。观察窗口要覆盖一个完整业务周期。

退出码 137 一定是内存问题吗?

137 表示进程被 SIGKILL,绝大多数情况是超出内存限制被强杀,但手动 kill -9 或编排平台强制终止也会产生同样的退出码。需要结合系统日志里的 oom-kill 记录确认。

定时重启算不算解决方案?

算止血,不算解决。可以作为过渡手段,但必须记录在案并设定复查时间。泄漏速度会随业务增长变快,某天重启周期就来不及了。

内存告警应该怎么设?

同时设两条:一条绝对水位(如持续超过 85%),一条增长趋势(如连续数小时单调上涨且无回落)。前者防容量不足,后者才能在泄漏早期发现问题。

资料来源

Linux OOM Killer 与 cgroup 内存限制的公开文档、主流容器运行时关于资源限制与退出码的说明,以及主流语言运行时的内存与垃圾回收官方文档。本文为通用运维说明,仅供参考,具体以实际运行时与编排平台为准。

相关阅读

网站访问日志留存与安全合规运维要点

为什么要留日志:这是法定要求 《网络安全法》第二十一条明确要求网络运营者"采取监测、记录网络运行状态、网络安全事件的技术措施,并按照规定留存相关的网络日志不少于六个月"。已完成备案、对外提供服务的网站属于网络运营者范畴,日志留存不是可选项,而是基础合规义务。 应留存哪些日志 | 日志类型 | 记录内容 | 主要用途 …

网站新增域名如何补充接入备案

企业在原有网站基础上新增域名,比如启用新的品牌域名或拼音域名指向同一网站时,不能直接绑定使用,而是需要在原备案基础上补充办理新增域名的接入手续。 新增域名前的准备工作 新增域名前,建议先确认该域名已经完成实名认证,可以通过 Whois查询 核对域名的注册信息和实名状态,避免因域名信息未实名导致接入申请被退回。同时确认…

备案信息年度核查该如何配合应对

部分省份的通信管理部门会对辖区内已备案网站开展年度或不定期核查,核查方式包括系统比对、电话回访、短信确认等,目的是确认备案信息与网站实际运营情况是否一致。 核查通常关注哪些内容 年度核查一般围绕主体信息、网站信息、接入信息三个维度展开,具体可以对照下表自查: | 核查维度 | 常见核查点 | | --- | --- …

备案号在网站上的规范展示与使用要求

网站完成备案只是第一步,备案号在页面上的展示方式同样需要长期维护,很多主体正是因为展示细节不规范,在日常巡查或年度核查中被要求整改。 展示位置与基本要求 通常做法是将备案号放置在网站首页底部,文字需清晰可辨、不被图片或广告遮挡,且格式应与下发的备案号文本保持一致,不能随意增减字符或调整顺序。是否需要加超链接指向查询入…

备案注销之后重新申请要注意什么

有些主体在此前因业务调整、接入商变更等原因注销了原有备案,之后又因新的业务需要重新申请备案。这种“二次备案”与首次备案在流程上大体相似,但有几个环节容易被忽略。 重新申请前的自查 重新申请前,建议先用 ICP备案查询 确认原备案是否确实已经完成注销,避免出现原备案未彻底清空、新申请与旧记录冲突的情况。同时检查计划使用…

备案信息变更有没有时效要求

备案不是办理完成后就一劳永逸的事项,主体信息、网站信息或联系方式一旦发生变化,通常需要在信息变化后的一定时间内完成变更提交,具体时限以属地管局要求为准。 哪些变化需要及时申报 常见需要变更的情形包括:主办单位名称或证件信息变化、网站负责人更换、联系电话或邮箱失效、网站域名调整、网站内容服务类型发生实质变化等。这类变更…

公司迁址之后备案地址信息如何更新

企业办公地址或注册地址发生变化后,备案信息中登记的地址项也需要相应更新,尤其是当迁址涉及跨区、跨市甚至跨省时,办理流程会比同城内迁址更复杂一些。 迁址后需要关注的信息 迁址后首先要确认工商登记信息是否已经完成同步变更,备案地址一般以工商登记的最新地址为准。可以先用 ICP备案查询 查看当前登记的主办单位地址,与最新的…

备案预留手机号邮箱变更该如何更新

备案信息中登记的手机号和邮箱,是管局与接入服务商联系网站负责人的主要渠道,用于发送核查通知、验证短信、审核结果等重要信息。这些联系方式一旦更换却未同步更新,容易导致关键通知被漏收。 常见需要更新的场景 负责人更换手机号或离职导致原号码停用; 企业邮箱系统迁移,原邮箱地址不再使用; 备案负责人变更,联系方式随之更换。 …

系统学习