服务端Too many open files解决方案

服务端Too many open files解决方案  

转自:http://zhumeng8337797.blog.163.com/blog/static/1007689142012428104618670/

cat /proc/sys/fs/file-nr 





近期系统上线,发现了一个很奇怪的问题,服务端运行没多久就出现页面打不开的现象,查看日志发现大量Too many open files,每台服务器以100MB/s的日志写入速度增加,没多久,每台服务器的日志都纷纷突破了10GB,显然连接数太大,服务器撑不住了,日志截图如下
< xmlnamespace prefix ="v" ns ="urn:schemas-microsoft-com:vml" />< xmlnamespace prefix ="o" ns ="urn:schemas-microsoft-com:office:office" />
 
 看到这样的景象,当然是首先逐台停止服务器(目前我们使用的是
Tomcat),删除日志,然后启动,但是这样显然维持不了很久又会出现相同的问题,为了不影响用户使用,当然需要两步一起走!
1、      逐台停止Tomcat,删除日志,增大系统可打开的文件连接数,启动Tomcat,恢复服务,保障用户服务正常!
2、      尽可能快的查出问题原因,从根源上解决问题。
那么,首先第一步,查看系统当前连接数是多少?使用命令ulimit –a查看
 
 显然,当前的
1024不能满足我们的需求,因此我们需要加大,Linux连接数最大为65536,我们就暂时设置为最大,让服务器多撑一会,给我们第二部的兄弟排查问题准备足够的时间,设置有很多方法,我在这里列举2种
1、  ulimit -n 65536,上图中已经提示我们使用-n查看对应的连接数,-n + value设置对应的数据值。如下截图所示
 
 这种设置方式非常方便快捷,但是这种设置只对当前登录用户的目前使用环境有效
,系统重启或者用户退出后就会失效。要想永久改变对应的值,需要采用第二种方案
2、  vim /etc/security/limits.conf 进行设置
修改/etc/security/limits.conf(里面有很详细的注释哦),在最下方添加
* soft nofile 65536
* hard nofile 65536
保存即可,这时候,需要重启Tomcat才生效
 
 这时候,使用
umilit –a 或者 ulimit –n查看的时候仍然是1024 当你退出重新登录以后就显示正常了(注意Tomcat要重启哦)
重新登录之前
 
 执行
exit 和login之后
 
 这样,按照之前的速度,还能多撑一个小时左右。
接下来就要彻查问题到底是出在什么地方了,继续监控Tomcat发现,Tomcat抛出了很多异常can't identify protocol,并且都是进程Java(即Tomcat的进程)抛出的,下面的问题就是can't identify protocoll是什么?是如何产生的?以前为何没有见过这个异常!
(注:使用lsof |grep java |grep 'identify protocol'查看Tomcat抛出的can't identify protocol错误数。)网上查询资料,发现can't identify protocol属于网络协议包丢失或者泄漏导致,以下是一段参考资料

问题定位步骤:
1、 用root帐户 遍历 /proc/进程ID/fd目录,如果该目录下文件数比较大(如果大于10,一般就属于socket泄漏),根据该进程ID,可以确认该进程ID所对应的名称。
2、 重启程序恢复服务,以便后续查找问题。
3、 strace 该程序并记录strace信息。strace –p 进程ID >>/tmp/stracelog.log 2>&1
4、 查看 /proc/进程ID/fd 下的文件数目是否有增加,如果发现有增加,记录上一个socket编号,停止strace
5、 确认问题代码的位置。打开/tmp/stracelog.log,从尾部向上查找close(socket编号)所在行,可以确认在该次close后再次创建的socket没有关闭,根据socket连接的server ip可以确认问题代码的位置。

另一种方法:判断是否有socket泄漏:
lsof | grep "can't identify protocol"
如果存在很多,则代表socket泄漏,同时会显示哪个进程使用的sock未关闭。
 
 也就是说,他使用了某个网络,但是这个网络发起了很多请求,却一直没有断开连接,怎么会造成这种现象的呢?但是值得肯定的是一定是向某个机器发起了请求但是却没有响应并且没有断开!
1、  接口调用,显然不会,接口都设置了半分钟超时,没有相应会自动断开,并且接口调用没有这么频繁,也不会这么快做重试操作!排除(X)
2、  数据库连接池,对于数据库来说,一般都设置了数据库连接池,也就是说最多创建多少个连接,每次从连接池中取数据,不可能有这么大的连接量!并且在机器重启后和刚开始系统服务正常,说明数据库连接正常,即便是数据库的问题,也是某些数据导致了异常,但是被限定于数据库连接池的大小,用监控发现,基本上这种车错误以5个/s的速度增长,而数据库连接不可能有这么大的量!排除(X)
3、  消息中间件,消息中间件采用ActiveMQ的方式进行异步通讯,设置有自动重连机制,并且使用长连接,有可能发生连不上重连的问题,但是消息中间件只要用于短信认证、邮件认证、订单交易的使用,不可能这么均匀的增长,并且查询数据库,当时的数据量也很小,检查消息中间件,工作正常,监控过程中有消息接受和消费,因此排除(X)
4、  缓存中间件,缓存中间件采用memcache做服务端存储,使用同步机制通讯,设置有自动重连机制,也有可能导致重连连不上一直连接的问题,排查缓存服务器,端口服务正常,但是发现了一块很奇怪的问题,缓存中的数据只有很少一部分,按照之前设计的,很多数据通过缓存存取,再查缓存命中率,发现近乎100%不命中,显然是缓存除了问题,但是服务正常,为何数据却没有写入的呢?于是马上入手,检查服务器到缓存的网络链路,发现是通的,那就是程序没有连接到这台机器上了,继续排查程序的配置文件,终于真相大白了,原来配置文件配置错误!连接的是研发环境的一台缓存服务器,而不是对应的服务器,而程序包通过AutoConfig推送,导致所有的分布式机器配置文件都是错误的(分布式为了更好的自动化部署机器,使用淘宝的AutoConfig处理配置文件一致的问题),每次系统先从缓存服务器取数据,如果取不到对应的数据则直接从DB取数据,从DB取完成数据后将数据缓存的对应的缓存服务器,但是此时缓存服务器不通,因此就产生可一个长连接失效的错误can't identify protocol,而memcache客户端又不停的尝试连接memcache(因为memcache是长连接),最终导致了大量的can't identify protocol产生,而大量can't identify protocol的产生导致了系统文件连接数过多,系统连接数过多在直接影响了Socket连接的打开与关闭,最终导致了系统的无法响应!命中(√)
问题找到了,修改就变得很简单了,修改为对的配置,重启Tomcat,果然can't identify protocol消失了,系统相应快了很多!
问题是解决了,但是有个很严重的问题,之前用的memcache客户端连不上主服务器的时候会抛出Socket异常,现在为什么不会了呢?还需要继续查找!




    今天发现运行好好的J2EE项目突然访问很慢,查看了一下日志报web.xml(Too many open files),google了一下发现时文件句柄数目不够所致。

    查看下一系统当前最大文件句柄数ulimit -n 得出为1024。对应一般应用1024够用了,但是对于像mysql、java等单进程处理大量请求的应用来说就有点捉襟见肘了。如果单个进程打开的文件句柄数量超过了系统定义的值,就会提到“too many files open”的错误提示。如何查看当前打开了多少文件句柄。执行:lsof -n |awk '{print $2}'|sort|uniq -c |sort -nr|more 。得出如下结果

[c-sharp] view plaincopy
  1. 697 30635  
  2. 155 14719  
  3.  95 2763  
  4.  73 2747  
  5.  70 20029  
  6.  70 18005  
  7.  69 24950  
  8.  69 24512  
  9.  69 24493  
  10.  69 24491  
  11.  69 23274  
  12.  69 18353  
  13.  68 24510  
  14.  68 24445  
  15.  68 23411  
  16.  68 23409  
  17.  68 23405  
  18.  68 23367  

这里我只截取了部分输出信息。其中第一行是打开的文件句柄数,第二行是进程号。执行ps -ef | grep 进程号 可查看进程的详细信息。

 

通过执行ulimit -HSn 4096 增大文件句柄数。这时候再执行ulimit -n发现已经变成4096了。

 

 

修改文件句柄数对所有用户都起作用

修改/etc/security/limits.conf,在文件末加上

* soft nofile 4096

* hard nofile 4096




前段时间帮助公司解决了一次tomcat环境服务器的异常,今天有时间过来总结一下。

 

问题的表现:

tomcat服务在重启之后,短时间内会承受大量访问,由于这个时候缓存还没建立,每次访问都将消耗一定资源(数据库连接或者文件IO),并发量在2000左右的时候tomcat服务开始抛出大量Too Many Open Files的异常,主要是文件IO一块的异常,数据库连接池配置恰当就不会抛异常。

 

问题分析:

这是一个典型的文件句柄耗尽的异常,在linux里头“一切皆文件”,所以虽然提示“文件”打开太多,其实也有可能是socket打开太多或者设备打开太多。

 

文件句柄是用来干嘛的?

 

  1. 句柄当做一个人的名字,并"可以通过名字(句柄),实现对句子的引用和访问",感觉这种比喻好象贴近,但问题是可能有许多人叫同一个名字,但句柄所以有意义正因为它具有唯一性,所以这种比喻也有问题,如果换个说法,说句柄是表示你的进程与外界的i/o连接,把它当作是一个连接的名字是不是更恰当些? 文件句柄是一个十六位长度的二进制代码(Windows95后为32位无符号整数),代表一个已被打开文件的通道号,借助于这个句柄,你的应用程序即可使用这个相应的句柄对文件进行随意存取操作,说白了文件句柄其实是一串代表着特殊含义的号码; 当然其实系统是用句柄与一些资源联系起来的,当由系统管理,动态分配给你应用程序的某些资源的代号,你就可以使用句柄访问相应的资源了,尤其在Windows系统中,有很多东东都使用句柄,如窗口,socket。  

简单看来程序通过句柄获得资源的引用,来进行资源的打开和关闭的操作。

 

为什么会出现文件句柄耗尽的情况?

 

主要是因为linux在文件句柄的数目上有两个级别的限制。

一个是系统级别的总数限制,

一个是针对用户的限制。


默认情况下每个用户所能使用的句柄数是1024。一般情况下1024也够用了,但是在大容量的系统上,特别是会频繁使用网络通信和文件IO的系统上,1024很快就被耗光了。所以首先我们要调整这个值。修改方法如下:

  1. 1. ulimit -a 查看当前用户的文件句柄限制  

  2. 2. 用户级别的句柄数限制修改。  
  3. 修改 /etc/security/limits.conf 增加下面的代码:  
  4. 用户名(或者用*表示所有用户)  soft nofile 65535    
  5. 用户名 hard nofile 65535   
  6. 有两种限制,一种是soft软限制,在数目超过软限制的时候系统会给出warning警告,但是达到hard硬限制的时候系统将拒绝或者异常了。  
  7. 修改之后可能需要重启shell生效。  

  8. 3. 系统级别的句柄数限制修改。  
  9. sysctl -w fs.file-max 65536  
  10. 或者  
  11. echo "65536" > /proc/sys/fs/file-max  
  12. 两者作用是相同的,前者改内核参数,后者直接作用于内核参数在虚拟文件系统(procfs, psuedo file system)上对应的文件而已。  
  13. 可以用下面的命令查看新的限制  
  14. sysctl -a | grep fs.file-max  
  15. 或者  
  16. cat /proc/sys/fs/file-max  
  17. 修改内核参数  
  18. /etc/sysctl.conf  
  19. echo "fs.file-max=65536" >> /etc/sysctl.conf  
  20. sysctl -p  
  21. 查看系统总限制 命令:cat /proc/sys/fs/file-max    
  22. 查看整个系统目前使用的文件句柄数量命令:cat /proc/sys/fs/file-nr   
  23. 查看某个进程开了哪些句柄 :lsof -p pid    
  24. 某个进程开了几个句柄 :lsof -p pid |wc -l    
  25. 也可以看到某个目录 /文件被什么进程占用了,显示已打开该目录或文件的所有进程信息 :lsof path/filename   

 

具体这个值应该设置成多少?

优先级(Open File Descriptors):
soft limit < hard limit < kernel < 实现最大file descriptor数采用的数据结构所导致的限制

 

其实这个值倒是没有具体限制,但是分配的值如果太大反而会影响系统性能,所以要根据具体应用调配权衡。

 

问题的解决方案:

首先当然是修改linux句柄数限制到一个合适的值。

然后就是应用本身的一个调整。有这么几种情况:

1.数据库连接池的优化。必须要使用连接池,否则句柄没耗光数据库就崩了。。。

2.抓取资源的时候有可能会用到HttpClient,尽量也应该使用连接池来控制连接数。

关于HttpClient的连接池配置可以查看我另外一文:http://blog.csdn.net/shootyou/archive/2011/05/12/6415248.aspx

3.连接池设置的把握,建立连接超时时间,读取超时时间,连接数目,等待时间,等都需要配置到一个合适的值,否则发挥不出连接池的性能。

 

一个负载比较重的discuz论坛服务器,1小时在线一万多,有时访问时无法显示。


我用另一台同网段的机器作测试,大概20次中会有1、2次超时


wget http://bbs.xxx.com
--17:06:08--  http://bbs.xxx.com/
正在解析主机 bbs.xxx.com... 221.13.18.b
Connecting to bbs.xxx.com|221.13.18.b|:80... 失败:连接超时。
重试中。
在bbs上用tcpdump监控


正常时可以接收到
......
17:27:55.746530 IP 221.13.18.a.39495 > 221.13.18.b.http: . ack 193785 win 353
17:27:55.746923 IP 221.13.18.a.39495 > 221.13.18.b.http: . ack 196705 win 353
17:27:55.747276 IP 221.13.18.a.39495 > 221.13.18.b.http: F 128:128(0) ack 197467 win 353
17:27:55.747284 IP 221.13.18.b.http > 221.130.185.a.39495: . ack 129 win 12

如果wget失败就监控不到信息,问下怎么回事?
检察了net.ipv4.tcp_max_syn_backlog 应该足够了


系统信息
======================================
centos 5.2 64bit
nginx+php+mysql

nginx 4个进程
php 96个进程


Linux bora 2.6.18-128.el5 #1 SMP Wed Jan 21 10:41:14 EST 2009 x86_64 x86_64 x86_64 GNU/Linux


sysctl内核
net.ipv4.ip_forward = 0
net.ipv4.conf.default.rp_filter = 1
net.ipv4.conf.default.accept_source_route = 0
kernel.sysrq = 0
kernel.core_uses_pid = 1
net.ipv4.tcp_syncookies = 1
kernel.msgmnb = 65536
kernel.msgmax = 65536
kernel.shmmax = 68719476736
kernel.shmall = 4294967296
net.ipv4.tcp_max_syn_backlog = 65536
net.core.netdev_max_backlog = 32768
net.core.somaxconn = 32768
net.ipv4.tcp_max_tw_buckets = 5000
net.core.wmem_default = 8388608
net.core.rmem_default = 8388608
net.core.rmem_max = 16777216
net.core.wmem_max = 16777216
net.ipv4.tcp_rmem = 4096 87380 16777216
net.ipv4.tcp_wmem = 4096 65536 16777216
net.ipv4.tcp_timestamps = 0
net.ipv4.tcp_synack_retries = 2
net.ipv4.tcp_syn_retries = 2
net.ipv4.tcp_tw_recycle = 1
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_mem = 196608 262144 393216
net.ipv4.tcp_max_orphans = 3276800
net.ipv4.tcp_fin_timeout = 30
net.ipv4.tcp_keepalive_time = 120
net.ipv4.ip_local_port_range = 1024  65535
net.ipv4.tcp_syncookies = 1


优化文件句柄
vi /etc/security/limits.conf
* soft nofile 51200 
* hard nofile 51200


vi /etc/rc.local
ulimit -SHn 51200 


===================
Active connections: 2419 
server accepts handled requests
73668795 73668795 232420556 
Reading: 11 Writing: 28 Waiting: 2380 



bbs在线会员 - 总计 13433 人在线

top - 13:29:01 up 33 days, 22:53,  2 users,  load average: 1.22, 1.60, 
Tasks: 265 total,   1 running, 264 sleeping,   0 stopped,   0 zombie 
Cpu(s):  9.3%us,  1.4%sy,  0.0%ni, 88.2%id,  0.5%wa,  0.0%hi,  0.6%si, 
Mem:   8168412k total,  6691148k used,  1477264k free,   917728k buffe 
Swap:  4096532k total,      228k used,  4096304k free,  3841696k cache


netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'
TIME_WAIT 4845
SYN_SENT 1
FIN_WAIT1 185
ESTABLISHED 2698
FIN_WAIT2 381
SYN_RECV 162
CLOSING 5
LAST_ACK 137


netstat -n |wc -l
8441


cat /proc/sys/net/ipv4/netfilter/ip_conntrack_max
65536


cat /proc/sys/fs/file-nr
4590    0       765985


proc/sys/fs/file-nr 
该文件与   file-max   相关,它有三个值: 


        *   已分配文件句柄的数目 
        *   已使用文件句柄的数目 
        *   文件句柄的最大数目   

该文件是只读的,仅用于显示信息。



典型的,提供大量静态文件访问的web服务器,缓存服务器(如squid), 均要注意这个问题


网上的教程,大约只是简单说明了如何设置ulimit和file-max, 但并没有说清楚这两者之间的差别,让人一头雾水


1. file-max的含义

man proc,可得到file-max的描述:

/proc/sys/fs/file-max
              This  file defines a system-wide limit on the number of open files for all processes.  (See
              also setrlimit(2),  which  can  be  used  by  a  process  to  set  the  per-process  limit,
              RLIMIT_NOFILE,  on  the  number  of  files it may open.)  If you get lots of error messages
              about running out of file handles, try increasing this value:

即file-max是设置
 系统所有进程一共可以打开的文件数量 。同时一些程序可以通过setrlimit调用,设置每个进程的限制。如果得到大量使用完文件句柄的错误信息,是应该增加这个值。


也就是说,这项参数是系统级别的。


echo  6553560 > /proc/sys/fs/file-max

或修改 /etc/sysctl.conf, 加入

fs.file-max = 6553560 重启生效


2. ulimit的

Provides control over the resources available to the shell and to processes started by it, on systems that allow  such control.


即设置当前shell以及由它启动的进程的资源限制。


显然,对服务器来说,file-max, ulimit都需要设置,否则就可能出现文件描述符用尽的问题,为了让机器在重启之后仍然有效,强烈建立作以下配置,以确保file-max, ulimit的值正确无误:


1. 修改/etc/sysctl.conf, 加入

fs.file-max = 6553560


2.系统默认的ulimit对文件打开数量的限制是1024,修改/etc/security/limits.conf并加入以下配置,永久生效

* soft nofile 65535 
* hard nofile 65535


修改完之后,重启即可生效



一、查看最大打开文件数

1、查看系统及最大打开文件数

  1. [root@localhost ~]# cat /proc/sys/fs/file-max
  2. 65535

2、查看当前用户最大打开文件数

  1. # ulimit -Hn //查看硬限制
  2. # ulimit -Sn //查看软限制

二、设置最大打开文件数

1、系统及的设置

  1. # vi /etc/sysctl.conf

增加:

  1. fs.file-max = 100000

立即生效:

  1. # sysctl -p

2、用户级设置

  1. vi /etc/security/limits.conf

设置如下:

  1. httpd soft nofile 4096
  2. httpd hard nofile 10240

httpd是用户,可以使用通配符*表示所有用户。
要使 limits.conf 文件配置生效,必须要确保 pam_limits.so 文件被加入到启动文件中。
查看 /etc/pam.d/login 文件中有:

  1. session required /lib/security/pam_limits.so

使用如下命令立即生效:

  1. # su - httpd
  2. $ ulimit -Hn 10240
  3. $ ulimit -Sn 4096
  1. 1、查看进程:ps -ef|grep [java、tomcat、weblogic]  
  2. 2、查看某端口TCP连接占用数:netstat -pnt | grep :6666 |wc -l  
  3. 3、查看某端口TCP连接占用信息:lsof -i :6666  
  4. 4、查看TCP连接状态以及数量:netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'  
  5. 5、查看所有进程占用的文件句柄数:lsof -n|awk '{print $2}'|sort|uniq -c |sort -nr|more  
  6. 6、查看某进程所属服务:ps -aef|grep 24204  


我的网站刚上线的时候过不了半天就会出现如下错误: 
Service Temporarily Unavailable 
The server is temporarily unable to service your request due to maintenance downtime or capacity problems. Please try again later. 

这种错误就是503.看到这种错误,第一想法就是BAIDU了.找到了一些解决方法!各家都有各自的意见和解决办法! 

首现谈谈网站的环境和配置. 

1、服务器WIN2003, 

2、TOMCAT5.5和APACHE2.2 

3、数据库是MSSQL2000 

差不多就这样了! 

看到这个办法,在服务器上测试,输入http://localhost:8080/index.do可以运行,但是输入http://locahost/index.do不行,出现503错误,怀疑中,怀疑1:TOMCAT和APAHCE通信出错. 

我的TOMCAT和APACHE的通信配置如下: 

在APACHE 

1、下载mod_jk-apache-2.2.4.so,把它放在APACHE目录下的modules下 

2、配置APACHE, 

LoadModule jk_module modules/mod_jk-apache-2.2.4.so 
JkWorkersFile "E:/Tomcat 5.5/conf/workers.properties" 
JkLogFile "E:/Tomcat 5.5/mod_jk2.log" 
JkLogLevel info 

3、在TOMCAT下的conf目录建立workers.properties文件,在文件中添加内 

ThreadsPerChild 100 
MaxRequestsPerChild 1000 
MaxMemFree 16 
ThreadLimit 100 
ThreadStackSize 8192 
KeepAliveTimeout 2 
MaxKeepAliveRequests 10 
Win32DisableAcceptEx 

认真看了一下,和在网上看了一些配置,差不多和我这个差不多,但是没有出错,本地测试也没有出错. 

看看APACHE出错的日志文件(error.log)其中出现了: 

[warn] (OS 64)指定的网络名不再可用. : winnt_accept: Asynchronous AcceptEx failed.和 

[warn] (OS 10038)在一个非套接字上尝试了一个操作. : setsockopt(SO_UPDATE_ACCEPT_CONTEXT) failed. 

是APACHE配置还有问题:在网上找了一下,好多人出现这个问题:大多数都是这样解决的,我也开始尝试.在APACHE中加入如下: 


ThreadsPerChild 100 
MaxRequestsPerChild 1000 
MaxMemFree 16 
ThreadLimit 100 
ThreadStackSize 8192 
KeepAliveTimeout 2 
MaxKeepAliveRequests 10 
Win32DisableAcceptEx 

重启TOMCAT和APACHE,可以用了,还认为解决了,但是过了一些时间,又出现503错误了,看来不是通信有错误,只要重启TOMCAT就好了,又查看APACHE日志文件,没有出现错误!此时又产生了一个怀疑,怀疑2:难道是TOMCAT和数据库的连接有问题. 

我网站开发的框架是(STRUTS和HIBERNATE和SPRING) 

难道是连接池的原因: 

以前是用DBCP配置的,在网上有人说这个有时候会出错,换了C3P0测试,问题依旧, 

我在WEB.XML中配置了OpenSessionInViewFilter 


 OpenSessionInViewFilter 
  
  org.springframework.orm.hibernate3.support.OpenSessionInViewFilter 
  
  
  singleSession 
  true 
  



 OpenSessionInViewFilter 
 /* 


难道是这个问题,找了一下,发现也有人出现这种情况引起了503错误.解决办法:在web.xml中加入如下配置 
  org.springframework.web.util.IntrospectorCleanupListener 


感觉可以了,充满希望重启TOMCAT,过了一阵子又出现503了,现在差不多崩溃了!怎么办,然后问了我同学(老廖)在这要特别感谢老廖和他的老大.给了我一些建.现在就轮到查TOMCAT的配置了. 

怀疑3:TOMCAT配置有问题. 

看了一下环境变量没有问题,看了一下没有错, 

看了一下TOMCAT的日志文件,出现了好多 

2008-10-22 12:00:09 org.apache.tomcat.util.threads.ThreadPool$ControlRunnable run 
严重: Caught exception (java.lang.OutOfMemoryError: Java heap space) executing org.apache.jk.common.ChannelSocket$SocketConnection@45b409, terminating thread 
2008-10-22 12:00:17 org.apache.commons.modeler.BaseModelMBean setManagedResource 
严重: Can’t set model mbean 
java.lang.OutOfMemoryError: Java heap space 
2008-10-22 12:00:23 org.apache.tomcat.util.threads.ThreadPool$ControlRunnable run 
严重: Caught exception (java.lang.OutOfMemoryError: Java heap space) executing org.apache.jk.common.ChannelSocket$SocketAcceptor@1931ec, terminating thread 

在网上查了一下是JVM内存泄漏引起TOMCAT昏厥,解决办法加大JVM内存,加入的办法如下:在catalina.bat加入一句 

set JAVA_OPTS=-Xms256m -Xmx1024m %JAVA_OPTS% 

把JVM的内存最大加到了1024M,哈,但是我的TOMCAT是安装版的,没有找到这个文件,只好另想办法.在tomcat5w.exe中有一个JAVA选项,那里就有设置最大和最小值的内存,看想是解决了.重启试一下.过了三天,没有出错了,网站运行正常,难道我解决了! 


netstat -n | awk '/^tcp/ {++state[$NF]} END {for(key in state) print key,"\t",state[key]}'

会得到类似下面的结果,具体数字会有所不同:

LAST_ACK 1
SYN_RECV 14
ESTABLISHED 79
FIN_WAIT1 28
FIN_WAIT2 3
CLOSING 5
TIME_WAIT 1669

状态:描述
CLOSED:无连接是活动的或正在进行
LISTEN:服务器在等待进入呼叫
SYN_RECV:一个连接请求已经到达,等待确认
SYN_SENT:应用已经开始,打开一个连接
ESTABLISHED:正常数据传输状态
FIN_WAIT1:应用说它已经完成
FIN_WAIT2:另一边已同意释放
ITMED_WAIT:等待所有分组死掉
CLOSING:两边同时尝试关闭
TIME_WAIT:另一边已初始化一个释放
LAST_ACK:等待所有分组死掉

也就是说,这条命令可以把当前系统的网络连接状态分类汇总。

下面解释一下为啥要这样写:

一个简单的管道符连接了netstat和awk命令。

------------------------------------------------------------------

先来看看netstat:

netstat -n

Active Internet connections (w/o servers)
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp 0 0 123.123.123.123:80 234.234.234.234:12345 TIME_WAIT

你实际执行这条命令的时候,可能会得到成千上万条类似上面的记录,不过我们就拿其中的一条就足够了。

------------------------------------------------------------------

再来看看awk:

/^tcp/
滤出tcp开头的记录,屏蔽udp, socket等无关记录。

state[]
相当于定义了一个名叫state的数组

NF
表示记录的字段数,如上所示的记录,NF等于6

$NF
表示某个字段的值,如上所示的记录,$NF也就是$6,表示第6个字段的值,也就是TIME_WAIT

state[$NF]
表示数组元素的值,如上所示的记录,就是state[TIME_WAIT]状态的连接数

++state[$NF]
表示把某个数加一,如上所示的记录,就是把state[TIME_WAIT]状态的连接数加一

END
表示在最后阶段要执行的命令

for(key in state)
遍历数组

print key,"\t",state[key]
打印数组的键和值,中间用\t制表符分割,美化一下。

如发现系统存在大量TIME_WAIT状态的连接,通过调整内核参数解决,
vim /etc/sysctl.conf
编辑文件,加入以下内容:

1.net.ipv4.tcp_syncookies = 1
2.net.ipv4.tcp_tw_reuse = 1
3.net.ipv4.tcp_tw_recycle = 1
4.net.ipv4.tcp_fin_timeout = 30

然后执行 /sbin/sysctl -p 让参数生效。

net.ipv4.tcp_syncookies = 1 表示开启SYN Cookies。当出现SYN等待队列溢出时,启用cookies来处理,可防范少量SYN攻击,默认为0,表示关闭;
net.ipv4.tcp_tw_reuse = 1 表示开启重用。允许将TIME-WAIT sockets重新用于新的TCP连接,默认为0,表示关闭;
net.ipv4.tcp_tw_recycle = 1 表示开启TCP连接中TIME-WAIT sockets的快速回收,默认为0,表示关闭。
net.ipv4.tcp_fin_timeout 修改系統默认的 TIMEOUT 时间

下面附上TIME_WAIT状态的意义:

客户端与服务器端建立TCP/IP连接后关闭SOCKET后,服务器端连接的端口
状态为TIME_WAIT

是不是所有执行主动关闭的socket都会进入TIME_WAIT状态呢?
有没有什么情况使主动关闭的socket直接进入CLOSED状态呢?

主动关闭的一方在发送最后一个 ack 后
就会进入 TIME_WAIT 状态 停留2MSL(max segment lifetime)时间
这个是TCP/IP必不可少的,也就是“解决”不了的。

也就是TCP/IP设计者本来是这么设计的
主要有两个原因
1。防止上一次连接中的包,迷路后重新出现,影响新连接
(经过2MSL,上一次连接中所有的重复包都会消失)
2。可靠的关闭TCP连接
在主动关闭方发送的最后一个 ack(fin) ,有可能丢失,这时被动方会重新发
fin, 如果这时主动方处于 CLOSED 状态 ,就会响应 rst 而不是 ack。所以
主动方要处于 TIME_WAIT 状态,而不能是 CLOSED 。

TIME_WAIT 并不会占用很大资源的,除非受到攻击。

还有,如果一方 send 或 recv 超时,就会直接进入 CLOSED 状态

netstat -an | grep SYN | awk '{print $5}' | awk -F: '{print $1}' | sort | uniq -c | sort -nr | more

  1. netstat -tna | cut -b 49- |grep TIME_WAIT | sort
    取出目前所有 TIME_WAIT 的连接 IP ( 排序过 )

  2.   net.ipv4.tcp_syncookies = 1 表示开启SYN Cookies。当出现SYN等待队列溢出时,启用cookies来处理,可防范少量SYN攻击,默认为0,表示关闭;
      net.ipv4.tcp_tw_reuse = 1 表示开启重用。允许将TIME-WAIT sockets重新用于新的TCP连接,默认为0,表示关闭;
      net.ipv4.tcp_tw_recycle = 1 表示开启TCP连接中TIME-WAIT sockets的快速回收,默认为0,表示关闭。
      net.ipv4.tcp_fin_timeout = 30 表示如果套接字由本端要求关闭,这个参数决定了它保持在FIN-WAIT-2状态的时间。
      net.ipv4.tcp_keepalive_time = 1200 表示当keepalive起用的时候,TCP发送keepalive消息的频度。缺省是2小时,改为20分钟。
      net.ipv4.ip_local_port_range = 1024 65000 表示用于向外连接的端口范围。缺省情况下很小:32768到61000,改为1024到65000。
      net.ipv4.tcp_max_syn_backlog = 8192 表示SYN队列的长度,默认为1024,加大队列长度为8192,可以容纳更多等待连接的网络连接数。
      net.ipv4.tcp_max_tw_buckets = 5000 表示系统同时保持TIME_WAIT套接字的最大数量,如果超过这个数字,TIME_WAIT套接字将立刻被清除并打印警告信息。默认为180000,改 为5000。对于Apache、Nginx等服务器,上几行的参数可以很好地减少TIME_WAIT套接字数量,但是对于Squid,效果却不大。此项参 数可以控制TIME_WAIT套接字的最大数量,避免Squid服务器被大量的TIME_WAIT套接字拖死。

     

     

    在怀疑有Dos攻击的时候,可以输入

    1 netstat -na | grep :80 |awk '{print $5}'|awk -F '::ffff:' '{print $2}' grep ':' awk -F: '{print $1}' sort uniq -c | sort -r | awk -F' ' '{if ($1 > 50) print $2}' sed's/^.*$/iptables -I firewall 1 -p tcp -s & --dport 80 --syn -j REJECT/' | sh

    先把冲击量最大的前50个IP给封了.

    还可以加几个例外的白名单IP

    1 netstat -na | grep :80 |awk '{print $5}'|awk -F '::ffff:' '{print $2}' grep ':' awk -F: '{print $1}' sort uniq -c | sort -r | awk -F' ' '{if ($1 > 50) print $2}' grep-v xxx.xxx.xxx.xxx | sed 's/^.*$/iptables -I RH-Firewall-1-INPUT 1 -p tcp -m tcp -s & --dport 80 --syn -j REJECT/' | sh
    以上的命令还没有实际考证过, 放在这里做参考.
展开阅读全文

Too many open files 报错信息

07-02

服务器配置:linuxrn服务:resin3.2 默认使用内存1024Mrnrnrnrnrnrnrnjava.io.FileNotFoundException: /www/tmp/digi/smallpic.properties (Too many open files)rn at java.io.FileOutputStream.open(Native Method)rn at java.io.FileOutputStream.(FileOutputStream.java:179)rn at java.io.FileOutputStream.(FileOutputStream.java:70)rn at com.tom.webutil.refresh.manager.BuildFile.bulidFile(Unknown Source)rn at _jsp._pages._getpice__jsp._jspService(_getpice__jsp.java:134)rn at com.caucho.jsp.JavaPage.service(JavaPage.java:60)rn at com.caucho.jsp.Page.pageservice(Page.java:570)rn at com.caucho.server.dispatch.PageFilterChain.doFilter(PageFilterChain.java:159)rn at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:75)rn at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:77)rn at com.caucho.server.dispatch.FilterFilterChain.doFilter(FilterFilterChain.java:70)rn at org.springframework.orm.hibernate3.support.OpenSessionInViewFilter.doFilterInternal(OpenSessionInViewFilter.java:174)rn at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:77)rn at com.caucho.server.dispatch.FilterFilterChain.doFilter(FilterFilterChain.java:70)rn at com.caucho.server.webapp.WebAppFilterChain.doFilter(WebAppFilterChain.java:178)rn at com.caucho.server.dispatch.ServletInvocation.service(ServletInvocation.java:229)rn at com.caucho.server.http.HttpRequest.handleRequest(HttpRequest.java:268)rn at com.caucho.server.port.TcpConnection.run(TcpConnection.java:389)rn at com.caucho.util.ThreadPool.runTasks(ThreadPool.java:492)rn at com.caucho.util.ThreadPool.run(ThreadPool.java:425)rn at java.lang.Thread.run(Thread.java:595) 论坛

java.net.SocketException too many open files

06-07

下面是错误信息:rn2013-6-3 11:10:52 org.apache.http.impl.client.DefaultRequestDirector tryConnectrn信息: I/O exception (java.net.SocketException) caught when connecting to the target host: Too many open filesrn2013-6-3 11:10:52 org.apache.http.impl.client.DefaultRequestDirector tryConnectrn信息: Retrying connectrnjava.net.SocketException: Too many open filesrn at java.net.Socket.createImpl(Socket.java:397)rn at java.net.Socket.getImpl(Socket.java:460)rn at java.net.Socket.setSoTimeout(Socket.java:1017)rn at org.apache.http.conn.scheme.PlainSocketFactory.connectSocket(PlainSocketFactory.java:126)rn at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:180)rn at org.apache.http.impl.conn.ManagedClientConnectionImpl.open(ManagedClientConnectionImpl.java:294)rn at org.apache.http.impl.client.DefaultRequestDirector.tryConnect(DefaultRequestDirector.java:640)rn at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:479)rn at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:906)rn at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:805)rn at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:784)rn at org.whu.weibo.util.NextPage.getPage(NextPage.java:48)rn at org.whu.weibo.content.NTESweibo.crawler(NTESweibo.java:42)rn at org.whu.Scan.scanByPage(Scan.java:27)rn at org.whu.Scan.run(Scan.java:17)rn at java.lang.Thread.run(Thread.java:662) 问答

没有更多推荐了,返回首页