Linux 系统报打开的文件过多

一、io.netty.channel.unix.Errors$NativeIoException: accept(..) failed: 打开的文件过多

1.问题

1804012290 [reactor-http-epoll-1] WARN  i.n.channel.DefaultChannelPipeline - An exceptionCaught() event was fired, and it reached at the tail of the pipeline. It usually means the last handler in the pipeline did not handle the exception. -
io.netty.channel.unix.Errors$NativeIoException: accept(..) failed: 打开的文件过多
2024-11-27 14:25:52.849  WARN 40110 --- [or-http-epoll-1] io.netty.channel.DefaultChannelPipeline  : An exceptionCaught() event was fired, and it reached at the tail of the pipeline. It usually means the last handler in the pipeline did not handle the exception.

2.查看linux默认连接数

ulimit -n

如果要查看是哪个进程打开的较多,可以使用

#使用ps -ef |grep java

#77281 表示进程id

lsof -p 77281 |wc -l

如果想查看 系统的一些限制参数,可以使用下面的

如果想查看当前系统设置的最大句柄数是多少,可以使用

ulimit -a

3.修改允许打开的文件数

3.1 修改允许打开的文件数——命令方式

这种设置方法是临时修改,在重启后会还原为默认值

3.1.1 vi /etc/profile

在文件末尾加入

#wx add 20241205
ulimit -n 65535

3.1.2 使其生效

source /etc/profile

3.2 修改允许打开的文件数——修改系统配置文件

这种设置方法会永久有效

vim /etc/security/limits.conf  
#在最后加入  
* soft nofile 65535  
* hard nofile 65535  

 * - nofile 65535

最前的 * 表示所有用户,可根据需要设置某一用户,例如

wux soft nofile 65535  
wux hard nofile 65535  

注意”nofile”项有两个可能的限制措施。就是项下的hard和soft。 要使修改过得最大打开文件数生效,必须对这两种限制进行设定。 如果使用"-"字符设定, 则hard和soft设定会同时被设定.


几个关于文件描述符的命令:

当前系统允许创建的最大文件描述符的数量

cat /proc/sys/fs/file-max

当前会话session的允许创建的最大文件描述符,默认每个进程允许打开的最大文件描述符数量应该是1024

ulimit -n

统计当前所有进程的占用的文件描述符的总量

lsof | wc -l

查看每个进程打开的文件描述符的数量,并按打开的数量降序排序:

lsof -n |awk '{print $2}'|sort|uniq -c |sort -nr

PS:lsof命令默认系统是没有安装的,需要执行下面的命令安装,此外这个命令需要用root执行:

yum install -y lsof


 

二、Socket accept failed java.io.IOException: Too many open files

在开发网络应用程序时,经常会遇到一些异常情况。例如java.io.IOException: Too many open files,这是由于系统限制了可同时打开的文件描述符数量而引起的。

问题的原因

在操作系统中,每个进程都有一个打开文件的限制。默认情况下,Linux和Windows系统的文件描述符限制分别为1024和2048。当应用程序打开的文件描述符数量超过限制时,系统将抛出java.io.IOException: Too many open files异常。

在网络编程中,当我们使用Socket进行通信时,每个Socket都会占用一个文件描述符。如果我们在处理连接时没有正确关闭Socket,或者并发连接数过多,就容易超过系统的文件描述符限制。

解决方案

要解决这个问题,我们需要采取以下几个步骤:

1. 检查系统文件描述符限制

首先,我们需要检查系统的文件描述符限制。我们可以使用ulimit -n命令来查看当前限制的大小。如果限制值太小,我们可以使用ulimit -n <new_limit>命令将其增加到一个较大的值。

2. 优化代码中的资源使用

接下来,我们需要检查代码中是否有资源没有正确关闭。确保在使用完Socket后,调用close()方法来关闭它。在使用try-with-resources语句块时,可以自动关闭资源。

try (Socket socket = new Socket()) {
    // 使用Socket进行通信
} catch (IOException e) {
    // 处理异常
}
3. 实现连接池

如果我们的应用程序需要同时处理大量的并发连接,那么使用连接池可以有效地管理和重用Socket资源。连接池可以限制并管理连接的数量,确保不会超出系统的文件描述符限制。

我们可以使用第三方库,如Apache Commons Pool,来实现连接池功能。下面是一个简单的示例代码,演示如何使用Apache Commons Pool实现连接池:

复制

GenericObjectPoolConfig<Socket> poolConfig = new GenericObjectPoolConfig<>();
poolConfig.setMaxTotal(100); // 设置最大连接数
poolConfig.setBlockWhenExhausted(true); // 当连接耗尽时,是否阻塞等待
poolConfig.setMaxWaitMillis(5000); // 最大等待时间(毫秒)

SocketFactory factory = new SocketFactory() {
    @Override
    public Socket create() throws Exception {
        return new Socket("localhost", 8080);
    }

    @Override
    public PooledObject<Socket> wrap(Socket obj) {
        return new DefaultPooledObject<>(obj);
    }
};

try (GenericObjectPool<Socket> pool = new GenericObjectPool<>(factory, poolConfig)) {
    Socket socket = pool.borrowObject(); // 从连接池中获取连接
    // 使用Socket进行通信
    pool.returnObject(socket); // 将连接返回到连接池
} catch (IOException e) {
    // 处理异常
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值