问题描述
我们的前端灰度服务在每次发布之后,占用的内存会一直增长,最终耗尽所有内存从而导致 OOM。
内存泄漏的场景
- 循环引用:如果多个对象互相引用,导致它们无法被释放。
- 不正确地使用Box或Rc:这些类型可以用于管理内存,但如果使用不当,也会导致内存泄漏。
- 忘记释放资源:确保所有分配的内存,文件,网络连接等资源都得到了及时释放。
排查工具
tokio-console
PageServer 使用了 tokio 这个异步编程库。tokio-console 是一个用于审查 tokio 运行时的工具,可以帮助我们查看异步任务的运行状态。参考文档添加相关的代码来引入。开发者启动 tokio-console 命令便可以查看异步任务的状态了。
# 安装 & 引入相关初始化代码
cargo install --locked tokio-console
# 默认链接端口为 6669
tokio-console http://127.0.0.1:5555jemalloc
既然没有出现异步任务的泄漏,那么接下来,只能去观察内存是如何分配的,那就必须要要使用到 jemalloc 了。需要在项目中引入这两个依赖:
tikv-jemallocator: 替换默认的内存分配器
jemalloc_pprof: 提供了导出 profile 文件的工具函数
将导出 profile 文件的逻辑包装成一个 http 接口,那么就可以运行过程中导出 profile 文件。在启动程序前,设置 export _RJEM_MALLOC_CONF=prof:true,lg_prof_interval:28 用以开启导出 profile 相关的功能。
jeprof 这款 cli 用来分析 profile 文件。当然也可以用 flamegraph.pl 来生成火焰图。
# 导出 profile 文件,并使用 jeprof 来分析
dump-profile() {
curl http://127.0.0.1:3000/debug/profile/prof > "$1.prof"
jeprof --svg ./target/release/page-server "$1.prof" > "$1.svg"
# 导出成火焰图, flamegraph.pl 来自于 https://github.com/brendangregg/FlameGraph/blob/master/flamegraph.pl
jeprof ./target/release/page-server "$1.prof" --collapse | perl flamegraph.pl > "$1.flamegraph.svg"
}
dump-profile 1k6
其实 k6 通常被当做压测工具来使用。不过借助它可以很方便的模拟出线上的请求。它的一个优点是可以通过 JavaScript 编写测试脚本。简单调整配置就可以模拟出线上的场景,对 前端 非常友好。
在安装完成了 k6 cli 后,使用 k6 new 生成测试脚本,执行 k6 run script.js 来执行测试。
import http from 'k6/http';
import { sleep } from 'k6';
export const options = {
// 同时请求的数量
vus: 10,
// 此次测试持续时长
duration: '30s',
};
export default function () {
const headers = {
host: `some-project.huolala.cn`,
timeout: '1s',
};
http.get(`http://127.0.0.1:3001/${path}`, { headers });
sleep(1);
}排查思路
- 导出线上 profile 文件来分析
- 使用 k6 来模拟线上请求,找出最小复现 demo
- 定位问题所在,修复 bug
问题分析与解决
通过对 profile 文件的分析,我们发现有两处地方存在较高的内存占用。
转载自:
https://juejin.cn/post/7477767063705337883 有实际案例建议观看