Skip to content

Linux Socket Exception #35

@johnnian

Description

@johnnian

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

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

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

四、参考链接

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions