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

bash 复制代码
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{}块,如下

bash 复制代码
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的头文件,差别如下

bash 复制代码
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);
相关推荐
半夜修仙2 天前
延迟队列的介绍及常见问题
java·数据库·中间件·rabbitmq
手握风云-2 天前
一条消息的旅程:RabbitMQ 学习与实践(一)
中间件·rabbitmq
RH2312112 天前
2026.6.8Linux
java·数据库·中间件
理人综艺好会3 天前
双Token机制在实际项目中的应用与实践
中间件·token
番茄去哪了4 天前
神领物流面试题(一)
java·大数据·中间件
念何架构之路4 天前
消息中间件
中间件
都说名字长不会被发现4 天前
Spring Boot Starter 中间件账号密码加密方案设计与实现
java·spring boot·后端·中间件
瀚高PG实验室4 天前
java中间件无法连接数据库
java·数据库·中间件·瀚高数据库
之歆5 天前
Day11_Express 深入解析:从中间件到项目实战
中间件·express
码农飞哥5 天前
RocketMQ消费接口设计实战:为什么HTTP回调接口必须吞掉所有异常,始终返回成功?
网络协议·http·中间件·消息队列·rocketmq