Open
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