Skip to content

Linux Socket Exception #35

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
johnnian opened this issue Sep 25, 2017 · 0 comments
Open

Linux Socket Exception #35

johnnian opened this issue Sep 25, 2017 · 0 comments
Labels

Comments

@johnnian
Copy link
Owner

johnnian commented Sep 25, 2017

一、遇到的问题 & 解决方法

在项目中,出现下面的几个问题:

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 : 获取系统允许打开的最大描述符数

四、参考链接

@johnnian johnnian added the Linux label Sep 25, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant