系统重启后nginx reload不生效原因分析
这是一种比较少见,困扰我很久的问题,虽然这个问题很简单,但是找到根本原因还是费了不少时间,现在把分析过程分享如下。 前提:需要对Linux系统启动过程、Nginx进程启动过程及进程跟踪有一定的理解。
一,Nginx reload过程分析:
经过查看官网文档及结合Nginx源码分析,大致得出reload过程进行了如下操作。 1,检查配置是否正确 相当于nginx -t 2,打开日志文件 相当于nginx -s reopen 由于日志文件比较多,需要打开多个文件 3,重新监听套接字 相当于nginx 这个步骤会初始化很多东西,重点关注哈希表 4,关闭旧worker进程 相当于nginx -s quit
二,nginx进程分析
1,首先了解nginx的两种进程 master进程,root用户打开,接收信号,管理worker进程 worker进程,nginx用户打开,工作进程,负责处理http请求 2,starce跟踪主进程号,期间执行nginx -s reload,发现卡在检查日志文件这块 主进程跟踪,因为reload过程是系统发送HUP信号给nginx主进程 #starce -p 2298
1 | open("/data/wwwlogs/access.xxx.xxx.xxx.log", O_WRONLY|O_CREAT|O_APPEND, 0644) = -1 EMFILE (Too many open files) |
3,根据提示,查找进程的系统限制文件 master进程限制
1 | # cat /proc/2398/limits |
worker进程限制
1 | # cat /proc/2300/limits |
补充错误日志:
1 | 2016/02/17 10:48:05 [notice] 47386#0: signal process started |
三,解决方案
1,修改限制 一般从以下3方面调优: 第一:nginx.conf参数规划与设置 worker_rlimit_nofile :限制单个工作进程打开的最大文件数: 线上配置没有问题 worker_rlimit_nofile 409600; 第二:系统级别的检查与设置 就是 /etc/security/limits.conf的配置与修改,请参考Linux系统资源限制汇总 线上配置没有问题
1 | * soft nofile 655350 |
第三:内核级别的检查与设置: fs.file-max值的大小设置: 线上配置比较大 fs.file-max = 6553600 注意:file-max的默认值大概是系统内存的10%(系统内存以kb计算) 2,验证生效 结果发现以上配置前期都有配置,但是重启服务器发现主进程的限制并没有修改过来,但是登陆服务器后无论在终端ulimit -n 查看还是关闭nginx主进程后重启nginx都生效了,由此推理出问题可能出在linux系统启动过程中,也就是说nginx主进程启动时,上面的限制配置没有生效,后来查阅资料发现系统启动后执行login时才会使limits.conf配置生效,所以需要调整顺序。 根据实际情况,系统启动过程如下: 1、读取/etc/inittab来读取默认级别 假设:读取到的默认级别是 3 2、执行初始化系统脚本 /etc/rc.d/rc.sysinit 来初始化脚本 3、然后执行 /etc/rc.d/rc 脚本 4、执行/etc/rc.d/rc.local脚本,此脚本是启动过程中最后启动的一个脚本。 最后会执行 /bin/login 登录用户。至此系统启动过程完成,login时才会执行/etc/profile,~/.bash_profile和~/.bashrc等,此时的ulimit -n查到的值不是nginx进程启动时的值。
默认用户登陆时会使limits.conf配置文件生效,这个比nginx进程启动晚,要在这之前使配置生效,需要补充配置如下: cat /etc/rc.local ulimit -HSn 655350 (注意在nginx启动前执行) /usr/local/nginx/sbin/nginx
四,补充优化
主要是相关参数调大了一些。 1,内核优化 net.ipv4.tcp_max_tw_buckets 修改大一些,减少内核负担,iptable本身对内核性能有影响
1 | # ss -an |awk '{print $1}'|sort |uniq -c |sort -rn |
线上修改配置如下: net.ipv4.tcp_max_tw_buckets = 18000 2,nginx优化 主要是哈希表,其他配置已经优化,哈希表有如下几种 server_names_hash可以加 map_hash可以加 types_hash够用 request header 不考虑 variables_hash 够用 线上修改配置如下: server_names_hash_max_size 512000; server_names_hash_bucket_size 64; (默认) map_hash_max_size 204800; map_hash_bucket_size 64; (默认)