您的位置:首页 > 运维架构 > Linux

解决Linux下“java.net.SocketException: Too many open files”异常

2012-08-17 11:46 621 查看
背景:

项目上线后发现Telnet模块在稳定运行一段时间后会自动断开,无法登陆,后台抛出:“java.net.SocketException: Too many open files”异常。

环境:

Java代码







Linux版本:cat /proc/version 
 
Linux version 2.6.18-164.el5 (mockbuild@x86-003.build.bos.redhat.com)
(gcc version 4.1.2
20080704 (Red Hat 4.1.2-46)) #1 SMP Tue Aug
18 15:51:48 EDT
2009 
 
Weblogic:10.3 
JDK:jrockit-jdk1.6.0_29-R28.2.2-4.1.0 

Linux版本:cat /proc/version

Linux version 2.6.18-164.el5 (mockbuild@x86-003.build.bos.redhat.com) (gcc version 4.1.2 20080704 (Red Hat 4.1.2-46)) #1 SMP Tue Aug 18 15:51:48 EDT 2009

Weblogic:10.3
JDK:jrockit-jdk1.6.0_29-R28.2.2-4.1.0


原因有以下两个:

1、打开的Socket客户端并没有正常关闭,此处可能是自动超时功能有问题或者网络突然断开等。

2、Linux默认设置的文件最大打开数太小(默认值:1024,使用:ulimit -n 命令查看)。

基于以上两点,故从以下三个方面着手解决:1、操作系统Linux 2、应用服务器Weblogic 3、程序

配置Linux文件最大打开数:

Java代码







/etc/security/limits.conf:在该文件的最后加入,最大文件打开数: 
 
* soft nofile 65535 
* hard nofile 65535 
 
/etc/pam.d/login:在该文件的最后加入: 
 
session required /lib/security/pam_limits.so 
 
重新登录后使用命令查看:ulimit -n,是否和设置保持一致 

/etc/security/limits.conf:在该文件的最后加入,最大文件打开数:

* soft nofile 65535
* hard nofile 65535

/etc/pam.d/login:在该文件的最后加入:

session required /lib/security/pam_limits.so

重新登录后使用命令查看:ulimit -n,是否和设置保持一致


3、修改Weblogic最大文件句柄数:(重启服务后生效)

Java代码







bea/wlserver_10.3/common/bin/commEnv.sh 

 
# limit the number of open file descriptors 
resetFd() { 
  if [ ! -n "`uname -s |grep -i cygwin || uname -s |grep -i windows_nt || \ 

       uname -s |grep -i HP-UX`" ] 
  then 
    ofiles=`ulimit -S -n` 
    maxfiles=`ulimit -H -n` 
    if [ "$?" =
"0" -a  `expr ${maxfiles} : '[0-9][0-9]*$'` -eq
0 -a `expr ${ofiles} : '[0-9][0-9]*$'` -eq
0 ]; then    
      ulimit -n 65535 
    fi 
  fi 


bea/wlserver_10.3/common/bin/commEnv.sh

# limit the number of open file descriptors
resetFd() {
if [ ! -n "`uname -s |grep -i cygwin || uname -s |grep -i windows_nt || \
uname -s |grep -i HP-UX`" ]
then
ofiles=`ulimit -S -n`
maxfiles=`ulimit -H -n`
if [ "$?" = "0" -a  `expr ${maxfiles} : '[0-9][0-9]*$'` -eq 0 -a `expr ${ofiles} : '[0-9][0-9]*$'` -eq 0 ]; then
ulimit -n 65535
fi
fi
}


4、优化 Linux TCP 配置:

Java代码







/etc/sysctl.conf 
 
# 2012-04-09 begin 

 
## 允许将TIME-WAIT sockets重新用于新的TCP连接,默认为0,表示关闭; 

net.ipv4.tcp_tw_reuse = 1 
 
## 表示开启TCP连接中TIME-WAIT sockets的快速回收,默认为0,表示关闭; 

net.ipv4.tcp_tw_recycle = 1 
 
##  修改系統默认的 TIMEOUT 时间 
net.ipv4.tcp_fin_timeout = 30 

 
## 表示当keepalive起用的时候,TCP发送keepalive消息的频度。缺省是2小时 

net.ipv4.tcp_keepalive_time = 1800 

 
## TCP发送keepalive探测以确定该连接已经断开的次数 
net.ipv4.tcp_keepalive_probes = 5 

 
## 探测消息发送的频率,乘以tcp_keepalive_probes就得到对于从开始探测以来没有响应的连接杀除的时间。 
net.ipv4.tcp_keepalive_intvl = 15 

 
## 表示SYN队列的长度,默认为1024,可以容纳更多等待连接的网络连接数 

net.ipv4.tcp_max_syn_backlog = 4096 

 
## 最大文件句柄数 
fs.file-max=65535 
 
# 2012-04-09 end 

 
# /sbin/sysctl -p 使上述配置生效命令 

/etc/sysctl.conf

# 2012-04-09 begin

## 允许将TIME-WAIT sockets重新用于新的TCP连接,默认为0,表示关闭;
net.ipv4.tcp_tw_reuse = 1

## 表示开启TCP连接中TIME-WAIT sockets的快速回收,默认为0,表示关闭;
net.ipv4.tcp_tw_recycle = 1

##  修改系統默认的 TIMEOUT 时间
net.ipv4.tcp_fin_timeout = 30

## 表示当keepalive起用的时候,TCP发送keepalive消息的频度。缺省是2小时
net.ipv4.tcp_keepalive_time = 1800

## TCP发送keepalive探测以确定该连接已经断开的次数
net.ipv4.tcp_keepalive_probes = 5

## 探测消息发送的频率,乘以tcp_keepalive_probes就得到对于从开始探测以来没有响应的连接杀除的时间。
net.ipv4.tcp_keepalive_intvl = 15

## 表示SYN队列的长度,默认为1024,可以容纳更多等待连接的网络连接数
net.ipv4.tcp_max_syn_backlog = 4096

## 最大文件句柄数
fs.file-max=65535

# 2012-04-09 end

# /sbin/sysctl -p 使上述配置生效命令


5、Java Socket程序中,增加如下配置:

Java代码







socket.setTcpNoDelay(true);
// 关闭Nagle算法, 立即发包 
socket.setKeepAlive(true); 

socket.setTcpNoDelay(true); // 关闭Nagle算法, 立即发包
socket.setKeepAlive(true);


6、常用Linux命令:(个人备忘)

Java代码







1、查看进程:ps -ef|grep [java、tomcat、weblogic] 

2、查看某端口TCP连接占用数:netstat -pnt | grep :6666 |wc -l 

3、查看某端口TCP连接占用信息:lsof -i :6666 

4、查看TCP连接状态以及数量:netstat -n | awk
'/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}' 

5、查看所有进程占用的文件句柄数:lsof -n|awk '{print $2}'|sort|uniq -c |sort -nr|more 

6、查看某进程所属服务:ps -aef|grep 24204 

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


9、优化结果

总共83把手持设备,现在24小时作业每天的TCP连接数保持在:70左右。以前一到600多系统就宕机了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息