问题现象:
日志出现大量“打开文件过多”异常信息
问题分析:
通过网上查询,发现是由于系统参数设置问题造成,因为应用并发量大,http连接多了,随之socket的消耗也多了,socket文件描述符也是Linux系统文件描述符的一种,Linux操作系统对此也有限制,所以需要调大参数fs.max-file和/etc/security /limits.conf的soft nofile和hard nofile值
解决方案:
通过设置以上参数,加大数值,重启应用。
问题再现:
设置了以上参数后,还以为问题可以解决,但是一段时间过后,问题继续出现。
问题分析:
通过对各服务器检测以上参数值发现有些服务器的设置不生效,回想当时设置后检查是发现生效的,但为什么忽然又一些服务器又不生效了。
问题思考:
现在的问题已经不是应用层上的问题,是操作系统级别的问题,测试发现,ssh登陆ulimit -n查询limit.conf不生效,但su登陆,limit.conf生效。
问题发现:
通过对Linux的一些学习,原来limit.conf配置文件是Linux PAM(插入式认证模块,Pluggable Authentication Modules)中 pam_limits.so 的配置文件。具体如何生效,还得看PAM如何配置。
继续研究:
应用进程的最大文件打开数是否跟当前会话的limit.conf参数值有关?如果通过ssh登陆启动应用是否跟ssh登陆会话时候额最大文件打开数有关,而su登陆启动应用,此时的应用进程是否就会跟当前的最大文件打开数关联,文件得到答复,写了一小段C代码测试:
#include<stdio.h> #include <unistd.h> #include<stdlib.h> #include<sys/resource.h> main() { struct rlimit limit; while(1){ getrlimit(RLIMIT_NOFILE,&limit); printf("the process canopen %d files\n",limit.rlim_cur); sleep(2); } }
这块代码是通过打印当前进程最大的文件打开书。经过测试,su进去的用户打开进程,打印的确实是limit.conf设置的值,而通过ssh进去执行这代码打印的却是修改limit.conf参数前的值(就是limit.conf没有生效)。这可能跟linux系统的进程、用户会话方面有关系,因为知识面窄,所以在论坛上提问了一下,网友就给了我我这样一个连接:http://linux.die.net/man/8/pam_limits。原文有这样一句话:“The pam_limitsPAM module sets limits on the system resources that can be obtained in auser-session. Users of uid=0 are affected by this limits, too.”这个pam_limits PAM在用户会话上有效,对0号进程(内核进程)也有是有效的。
关联疑问:
我们平时的操作时都是通过终端去操作的,开启进程的父进程都是当前终端进程,例如ssh,但有一些进程是在后台运行的。当开启了后,关闭终端,那他们归属谁呢?通过观察发现。这些孤独的进程都是被1号进程接收了。这里可能就涉及到linux进程管理的问题了。暂不再深入研究。
我想到了一种情况,如果我用ssh进去开启进程,这父进程的ID是我这ssh进程。当我退出ssh后,那个子进程没有关闭就归1号进程管了(例如我们常见的java进程)。那这个子进程的最大文件打开数会不会就变回limit.conf文件设置的值呢?因为ssh进程进去的值是limit.conf修改前的值。ssh进去开启我那测试进程打印的确实是跟当前的limit.conf值不一样,就是没有生效。我又在网上找到了一个方法,直接把那测试代码的子进程直接赋予给1号进程:setsid。经过测试,打印出来的最大文件打开数没变。就像上面说的这个PAM设置跟用户会话有关系。
测试over。以后发现有问题,继续跟进。