关闭

linux文件句柄不足导致服务器僵死

标签: 服务器linux应用服务器jmx测试socket
2075人阅读 评论(2) 收藏 举报
分类:

  测试组同事做性能测试的时候,Web容器在NIO模式下,用1000个并发做压力测试。同事一般使用jconsole连接到应用服务器实例的JMX MBean Server监控内存变化和线程变化情况。但是前两天发现并发上去之后,jconsole不能获得数据了,不能做任何监控了,并且jconsole的报下面的错误

                   

 

  初一看,这问题不好解决呀,感觉很朦胧,但是静下心来想想,还是有条理地解决吧,分析思路如下:

   1,从堆栈分析得出,jconsole肯定是取某个MBean(最后查出是MBean ObjectName为:java.lang:type=OperatingSystem的这个MBean),所以写了一个很简单的JMX Client做while循环取java.lang:type=OperatingSystem的CommittedVirtualMemorySize。发现简单的客户端也出错,便用修改JMX Client为两种方式,一种是在while循环里面try catch(也就是说当取失败之后仍然继续调用MBean取属性),一种是try catch里面做while循环,也就是一旦取失败之后,整个JMX Client的Java就会退出了。猜测JConsole之所以停滞就是因为JConsole的机制是:一旦出现异常就不去获取了,也就是等同于我的简单Client在try catch里面做循环。

  2,简单的Client和jconsole都是连接到应用服务器实例的MBeanServer上的,jconsole的控制台报的错误就是连接的MBeanServer所在的JVM进程的错误,所以就重点查服务器实例(就是JConsole连接的MBeanServer所在的jvm进程)获取CommittedVirtualMemorySize的操作。

 

  看了JDK的代码之后

  3,知道UnixOperatingSystem的getCommittedVirtualMemorySize是个本地方法,再加上报Unable to open /proc/self/stat错误,感觉和操作系统可能有一点关系。就有做了一次压力测试,同时监控jconsole和服务器实例的日志,这一测试发现,在jconsole报错之前服务器实例报了一个"too many open files",这日志一看,就比较明了了,几乎可以肯定是与文件描述符显示有关系。

  4,继续再做压力测试的同时用命令监控文件句柄数量(while(true) do /usr/sbin/lsof -p $应用服务器java进程的pid | wc -l;sleep 1;done),发现这一数据有最初的140多飙升至1132左右之后,jconsole就会停止,服务器实例的日志也会把异常。就在1132数据的时候用(/usr/sbin/lsof -p $应用服务器java进程的pid > lsof.txt),查看输出的结果,发现http端口18080所占的端口的Socket连接达到991个,问题已经水落石出了,就是同一个进程占用的文件句柄数(Socket也算是文件句柄)超过了默认的1024.

 

  解决办法:

 1,修改/etc/security/limits.conf文件,在末尾增加一行,增大文件句柄限制数量,如下

 bes soft nofile 2000//四个数据依次是用户(可以使用*标识所有用户),类型(soft和hard两种),限制的属性(打开文件句柄数量/文件大小等等都可以限制),限制属性具体的值 ||||我这个配置的意思就是现实bes用户打开文件句柄最大为2000,这样1000个并发过来也没问题。

 2,网上说ulimit -Sn 2000类似的命令也可以,但是好像ulimit对用户限制较多,只有root用户才能修改nofile这个属性,并且ulimit命令修改的话只对当前用户有效。

  所以修改配置文件是比较好的解决方案。

 

  问题解决了,解决问题往往涉及到很多方面的知识,操作系统,编程语言,网络知识,甚至到数据库等等。要想成为高手,路还远。

0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:57681次
    • 积分:802
    • 等级:
    • 排名:千里之外
    • 原创:20篇
    • 转载:4篇
    • 译文:0篇
    • 评论:17条
    最新评论