Skip to content

[RFC] 快照在内存毛刺时的自动 Dump 机制 #102

Open
@hyj1991

Description

背景

阅读 一个平均运行一百万次才出现一次的bug,你如何调试这个bug 结合最近的语雀偶发性 Coredump 想到

堆内存的异常不同于 CPU,偶发性的异常请求导致的内存毛刺,也是需要关注的,但是由于是瞬时的内存上涨,不易排查:

  • 本身并非内存泄露,而是异常请求处理逻辑自身需要申请异于正常请求的堆空间
  • 异常请求在插件采集的那一刻已经处理完成,内存恢复正常水位,导致监控无法正常预警
  • 就算恰好采集到异常内存点,监控服务正常给出预警,等开发者收到通知前往控制台时已经无法获得问题快照

另一种和前文类似的场景,异常请求造成了 OOM,正常生成了 Core 文件,存在以下场景导致无法定位

  • 异常请求造成堆内存飙升但是尚未 OOM
  • 正常请求处理申请申请的堆内存成为最后一根稻草,导致 OOM
  • Core 的 Btrace 包含的是最后的正常请求

这种情况下只能通过逆工程 V8 Heap object 来进行进一步问题定位,由于在 core 文件里还原的 Heap object 丢失了 GC root 信息,所以没有办法进行 Dominator tree 的构建,人肉扫除了大字符串类,很难甄别内存泄漏点。

综上 Xprofiler 插件需要提供一个机制,在内存出现毛刺时进行自动 Dump 来辅助这类问题的定位。


具体设计

  • 新增一个 1s 粒度的巡检 Thread
  • 分别构造 int[60 * 60] Ring buffer 存储过去 1min 内的进程 CPU / Heap 大小
  • 每次存储前比较当前 CPU / Heap 大小和历史 1h 内均值,超过阈值则进行自动 Dump
    • 阈值可配置,可动态修改
  • 此功能为可选配置,默认关闭(没有这种场景需求 / 介意额外的性能损耗)
    • 可动态修改开闭状态

存在的副作用

  • 额外的存储开销:60 * 60 * 4 * 2 约 28MB 常驻内存
    • 这里可以通过将 Ring buffer 大小设计为可配置来动态调整
  • 额外的巡检 Thread 的 CPU 开销(可忽略不计)

需要处理的异常场景

  • 一段时间内出现大量毛刺,需要控制只对其中之一进行 dump,防止一次性大量 dump 打垮进程
  • TODO,暂时还没想到

监控服务端的改造

  • 新增主动通知类的告警
  • 增加 xprofiler 配置界面修改下发

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions