nginx 解决进程内存占用翻倍
本文分享自天翼云开发者社区《nginx解决进程内存占用翻倍》.作者:z****n
1.问题
某天,线上生成环境发现一个问题:
某一台机器线上的 nginx 进程占用的内存是其他机器的 2 倍 ,尝试对 nginx 进行 reload 后,并没有恢复
内存占用翻倍机器:
正常机器:
2.分析
1.每次 reload 或者启动时 worker 进程从 master 进程 fork 出来,所以 reload 后 worker 进程的内存和 master 进程内存大小应该保持一致。
2.由于 master 进程 reload 时,是先用一个全新的结构体解析配置后,再 free 释放到原有配置的结构体。所以 master 进程再 reload 过程,会短暂的保持 2 个结构体(内存 2 倍),再变为 1 个全新配置结构体(内存正常)。所以猜测 2 倍的原因和这个原理有关,很可能是内存泄漏,没有释放原有结构体。
3.内存占用 2 倍的机器上对 nginx 进行不断的 reload,发现内存保持不变,依然保持 2 倍。所以推翻第 2 步的猜测,若是 nginx 内存泄漏,那每次 reload 都会造成内存不断增长,而不是一直保持 2 倍状态
4.由于 nginx 中使用的是 glibc 的 malloc/free, 即在程序中调用 malloc 函数开辟一段空间后,再次调用 free 函数,程序会把开启的空间还给 glibc,但是 glibc 不一定会把内存还给操作系统。除非调用 malloc_trim(0)。所以怀疑大概率要加上一个 malloc_trim(0)
3.复现
1.准备
在本地机器上准备一个简单的 nginx,nginx 中包含众多的 server{} 配置(server 数量多时候比较好复现)
nginx.conf 配置如下
server 目录如下中是一堆 server{}块,如下
2.测试
启动 nginx,观察当前内存
进行 reload 操作,观察当前内存,发现内存翻了一倍
4.解决
在 src/os/unix/ngx_process_cycle.c 中 解析完新配置释放旧的配置的结构体后,增加一行 malloc_trim(0)后,重新编译。再次启动 nginx, reload 后,观察内存不会翻倍
有的 nginx 中使用了 jemalloc 中替换了 glibc 也可能遇到这个问题,需要把 malloc_trim 函数 替换为 mallctl 函数,同时加上 3 个 jemalloc 的头文件,差别如下







评论