nginx内存无法释放?
某次线上排查问题的时候发现一个奇怪的问题,线上nginx 有的worker进程占用内存是其它worker 的2倍,并且master进程占用内存一定是占用内存低worker进程的2倍。
排查过后发现是nginx解析配置时候,会把解析的配置存到一个结构体,当nginx reload 的时候,master进程会先把配置解析到一个新的结构体,解析没问题后,再调用free()函数释放旧的结构体,把内存释放給glibc ,而glibc不会立即释放内存給操作系统
glibc释放内存: https://blog.csdn.net/u013093948/article/details/53337992
实验:
1.首先执行如下脚本生成多个server的test.conf
```
#!bin/bash
for i in `seq 1 10000`
do
echo "server {" >> test.conf
echo " listen 80;" >> test.conf
echo " server_name test.${i}.com;" >> test.conf
echo " location / {" >> test.conf
echo " }" >> test.conf
echo "}" >> test.conf
done
```
2.在nginx.conf 中添加
```
http {
include test.conf;
}
```
3.启动nginx并观察内存占用
#/usr/local/nginx/sbin/nginx
#ps -aux | fgrep nginx
root 14827 0.0 0.1 176648 129652 ? Ss 11:11 0:00 nginx: master process /usr/local/nginx/sbin/nginx
nobody 14831 0.0 0.1 176648 129932 ? S 11:11 0:00 nginx: worker process
nobody 14833 0.0 0.1 176648 130152 ? S 11:11 0:00 nginx: worker process
nobody 14836 0.0 0.1 176648 130152 ? S 11:11 0:00 nginx: worker process
nobody 14838 0.0 0.1 176648 129912 ? S 11:11 0:00 nginx: worker proces
4.执行nginx reload 并观察内存占用
#/usr/local/nginx/sbin/nginx -s reload
#ps -aux | fgrep nginx
root 14827 0.2 0.3 300400 253956 ? Ss 11:11 0:00 nginx: master process /usr/local/nginx/sbin/nginx
nobody 14836 0.0 0.1 176648 130156 ? S 11:11 0:00 nginx: worker process is shutting down
nobody 29692 0.0 0.3 300400 253556 ? S 11:13 0:00 nginx: worker process
nobody 29693 0.0 0.3 300400 253556 ? S 11:13 0:00 nginx: worker process
nobody 29694 0.0 0.3 300400 253556 ? S 11:13 0:00 nginx: worker process
nobody 29695 0.0 0.3 300400 253556 ? S 11:13 0:00 nginx: worker process
5.发现内存占用果然升上去了
6.知道原因后也好解决,在要稍微修改下源码,在reload后马上释放内存即可
--- a/src/os/unix/ngx_process_cycle.c
+++ b/src/os/unix/ngx_process_cycle.c
@@ -9,6 +9,11 @@
#include <ngx_core.h>
#include <ngx_event.h>
#include <ngx_channel.h>
+#if (NGX_JEMALLOC)
+#include <jemalloc/jemalloc.h>
+#include <jemalloc/internal/jemalloc_internal_defs.h>
+#include <jemalloc/internal/util.h>
+#endif
static void ngx_start_worker_processes(ngx_cycle_t *cycle, ngx_int_t n,
@@ -238,6 +243,14 @@ ngx_master_process_cycle(ngx_cycle_t *cycle)
continue;
}
+ /* release memory back to the system */
+#if (NGX_JEMALLOC)
+ mallctl("arena." STRINGIFY(MALLCTL_ARENAS_ALL) ".purge", NULL, NULL, NULL, 0);
+#else
+ malloc_trim(1);
+#endif
+ ngx_msleep(100);
+
ngx_cycle = cycle;
ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx,