-
Notifications
You must be signed in to change notification settings - Fork 59
Open
Labels
Description
一、遇到的问题 & 解决方法
在项目中,出现下面的几个问题:
1、java.net.SocketException: Too many open files
Caused by: java.net.SocketException: Too many open files
at java.net.Socket.createImpl(Socket.java:460)
at java.net.Socket.getImpl(Socket.java:520)
at java.net.Socket.setSoTimeout(Socket.java:1141)
排查了下,是因为系统的 "Open File" 参数比较低,默认是 1024:
[root@bb7122794dd0 ~]# ulimit -n
1024
「Open File」 这个参数,限定了 每个进程可以打开的最大文件描述符数(File Descriptors), 创建 Socket、打开文件等操作,都会影响文件描述符的值。
因此,简单的解决方法是,提升操作系统的文件描述符限值:
修改操作系统允许打开的最大 文件描述符 数:
[root@bb7122794dd0 ~]# vi /etc/sysctl.conf
#添加或修改
fs.file-max = 6553560
修改单个进程允许打开的最大 文件描述符 数:
永久改变
[root@bb7122794dd0 ~]# vi /etc/security/limits.conf
* hard nofile 65535
* soft nofile 65535
仅当前登录shell生效,退出后就失效
[root@bb7122794dd0 ~]# ulimit -n 4096
配置完成后,重启服务器即可生效。
2、java.net.SocketException: Connection reset
java.net.SocketException: Connection reset
at java.net.SocketInputStream.read(SocketInputStream.java:209)
at java.net.SocketInputStream.read(SocketInputStream.java:141)
原因: Client 或者 Server, 一方已经关闭Socket连接,另一方还在写数据,就会抛出改异常。也就是说,这个异常是因为Socket连接断开后的读和写操作引起的。
解决方法:目测是因为“Open File”参数低导致,也需要排查下程序,确保在异常的情况下,所有的Socket连接都要断开。
3、java.net.SocketException: Broken pipe
Caused by: java.net.SocketException: Broken pipe
at java.net.SocketOutputStream.socketWrite0(Native Method)
at java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:109)
at java.net.SocketOutputStream.write(SocketOutputStream.java:153)
原因:如果程序在报 java.net.SocketException: Connection reset 后,还继续读写,则抛出改异常,解决方法同上。
4、出现大量的 TIME_WAIT & CLOSE_WAIT
- TIME_WAIT: 主动关闭连接的一方保持的状态, 通常是维护人员手动Kill掉服务器进程导致,可以通过系统参数调优,缩短等待时间;
- CLOSE_WAIT: 由于一方在通讯异常等情况下,没有对建立的Socket进行关闭操作,就会出现
CLOSE_WAIT, 需要检查对应的代码。
解决方法:
- TIME_WAIT 优化: 参考文章最后面的链接方法;
- CLOSE_WAIT: 检查程序代码的问题,比如出现异常的情况下,是否有关闭连接的处理等;
二、基本概念
1、File Descriptors
维基百科
文件描述符在形式上是一个非负整数。实际上,它是一个索引值,指向内核为每一个进程所维护的该进程打开文件的记录表。当程序打开一个现有文件或者创建一个新文件时,内核向进程返回一个文件描述符。
Linux 限制每个进程能够打开的文件描述符的数,默认是 1024,文件操作、Socket通讯、TCP通讯操作都会影响Open Files的值。
三、常用命令
- ulimit -n : 查看每个进程的最大 Open File数
- lsof | wc -l : 统计当前系统所有进程已经用的文件描述符数
- lsof [PID] | wc -l : 统计具体进程已经用的文件描述符数
- cat /proc/sys/fs/file-max : 获取系统允许打开的最大描述符数