searchusermenu
  • 发布文章
  • 消息中心
点赞
收藏
评论
分享
原创

nginx解决进程内存占用翻倍

2023-07-31 04:40:07
144
0

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 配置如下

worker_processes  1;
error_log  logs/error.log  debug;
events {
    worker_connections  1024;
}

http {
    include       mime.types;
    default_type  application/octet-stream;
    server_names_hash_max_size 8192;
    server_names_hash_bucket_size 256;
    server {
        listen 80;
        location / {
            root html;
        }
    }
    include server/*.conf;
}

server 目录如下中是一堆server{}块,如下

server {
        listen 80;
        server_name www.a.com1;
        location / {
                return 200 okokokokok;
        }
 }
server {
        listen 80;
        server_name www.a.com2;
        location / {
                return 200 okokokokok;
        }
 }
####大量不同server_name 的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的头文件,差别如下

12,15d11
< #include <jemalloc/jemalloc.h>
< #include <jemalloc/internal/jemalloc_internal_defs.h>
< #include <jemalloc/internal/util.h>
< 
235c231
< 	    mallctl("arena." STRINGIFY(MALLCTL_ARENAS_ALL) ".purge", NULL, NULL, NULL, 0);
---
> 	    malloc_trim(0);
0条评论
作者已关闭评论
z****n
4文章数
0粉丝数
z****n
4 文章 | 0 粉丝
原创

nginx解决进程内存占用翻倍

2023-07-31 04:40:07
144
0

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 配置如下

worker_processes  1;
error_log  logs/error.log  debug;
events {
    worker_connections  1024;
}

http {
    include       mime.types;
    default_type  application/octet-stream;
    server_names_hash_max_size 8192;
    server_names_hash_bucket_size 256;
    server {
        listen 80;
        location / {
            root html;
        }
    }
    include server/*.conf;
}

server 目录如下中是一堆server{}块,如下

server {
        listen 80;
        server_name www.a.com1;
        location / {
                return 200 okokokokok;
        }
 }
server {
        listen 80;
        server_name www.a.com2;
        location / {
                return 200 okokokokok;
        }
 }
####大量不同server_name 的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的头文件,差别如下

12,15d11
< #include <jemalloc/jemalloc.h>
< #include <jemalloc/internal/jemalloc_internal_defs.h>
< #include <jemalloc/internal/util.h>
< 
235c231
< 	    mallctl("arena." STRINGIFY(MALLCTL_ARENAS_ALL) ".purge", NULL, NULL, NULL, 0);
---
> 	    malloc_trim(0);
文章来自个人专栏
zengjj的专栏
4 文章 | 1 订阅
0条评论
作者已关闭评论
作者已关闭评论
0
0