Q68: 如何设计内存监控?
核心结论
内存监控的目标不是“每秒打印一次内存值”,而是能够回答:
- 内存为什么在涨
- 涨的是哪一类对象
- 是泄漏、峰值还是正常缓存波动
- 什么时机应该报警,什么时机只是观察
如果监控只能看到总量,却看不到结构和趋势,线上定位价值会很低。
一、先区分几类内存问题
监控设计前,先明确想识别的对象:
- 持续增长型泄漏
- 周期性峰值
- 缓存膨胀
- 碎片或分配抖动
这些问题从总 RSS 上看都像“内存高了”,但根因完全不同。
二、只看总内存远远不够
至少应该分层观察:
- 进程总量
- 模块级占用
- 分配频率
- 关键对象数量
- 大块内存来源
否则只能知道“机器快满了”,却不知道该改哪里。
三、内存监控应同时关注量和变化趋势
有价值的监控不仅是当前值,还包括:
- 增长速度
- 峰值和回落
- 版本间对比
- 高峰场景前后差异
很多泄漏在短时间内看不明显,但趋势很清楚。
四、关键对象统计往往比 allocator 细节更有用
在线游戏里很值得统计的通常包括:
- 实体数量
- 定时器数量
- 消息队列积压
- 缓存条目数
- 特定大对象池占用
因为很多内存问题根本不是底层分配器坏了,而是业务对象数量异常。
五、报警策略必须克制
内存报警如果只按单一阈值,很容易误报。
更合理的做法通常是结合:
- 当前值
- 增长趋势
- 持续时间
- 是否接近系统极限
这样才能区分“正常高峰”和“异常失控”。
六、线上和离线分析要配合
线上监控更适合:
- 轻量统计
- 趋势观察
- 快速告警
离线分析更适合:
- 堆快照
- 泄漏定位
- 对象分布分析
两者不是替代关系,而是配套关系。
七、工程上更稳妥的设计
常见做法是:
- 进程级指标常驻采集
- 模块和对象级统计定期上报
- 高风险场景支持按需抓样
- 泄漏问题通过快照和 profiling 进一步定位
这样既不会把监控本身做得太重,也能保留定位能力。
八、常见误区
1. RSS 稳定就说明没问题
不一定。对象池膨胀、碎片化和热点峰值也可能隐藏在稳定总量里。
2. 报警阈值设低一点更安全
太低会制造噪音,让真正的异常被淹没。
3. 只有泄漏才值得监控
峰值、缓存膨胀和队列积压同样会拖垮系统。
参考资料
- 内存监控、堆分析和线上告警实践资料
