关于循环Socket创建超Linux文件句柄限制现象分析

embedded/2024/9/23 23:21:15/

项目场景:

在操作系统的世界中万物皆文件。之前拜读过一些作品:针对于socket的创建,Linux也相应创建文件(专业术语中也称文件句柄),于是,我想做一些关于极限的操作,看看这些极限操作会出现什么样的报错,以及相应的解决方案是什么。


问题描述

博主的主语是Java,所以,用Java编写一段程序试试看,观察观察:

java">import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Socket;public class FileOpenTest{public FileOpenTest() throws Exception{}public static void main(String[] args) throws Exception{int numberOfSockets = 189412;Socket[] sockets = new Socket[numberOfSockets];for(int i = 0; i < numberOfSockets; ++i) {try {int port = 8000 + i;sockets[i] = new Socket();sockets[i].connect(new InetSocketAddress("198.1.108.211", 22));System.out.println("Socket " + i + " connected to port " + port);System.out.println(i);} catch (IOException var5) {IOException e = var5;e.printStackTrace();Thread.sleep(Integer.MAX_VALUE);return;}}}
}

部署到服务器198.1.108.210,运行程序后报以下错误:

java.net.SocketException: Too many open files
at java.base/java.net.Socket.createImpl(Socket.java:479)
at java.base/java.net.Socket.connect(Socket.java:606)
at java.base/java.net.Socket.connect(Socket.java:557)
at FileOpenTest.main(FileOpenTest.java:17)

另外,同样的代码在windows上的报错如下:
创建了有16288socket,跟Linux上的限制数值不一样,这应该是windows的设置。
在这里插入图片描述


原因分析:

于是博主先顺藤摸瓜,找找网上对应的解决方案,最终找到了一篇比较满意的答案。参考
阅读原文之后并实践之后,发现是Linux操作系统这个硬限制参数限制了:
文件句柄限制:

#硬限制
ulimit -Ha
#软限制
ulimit -a 
ulimit -Sa

至于硬软限制的区别,网上说是软限制仅会发出警告,而硬限制则会报错


解决方案:

提示:这里填写该问题的具体解决方案:

例如:新建一个 Message 对象,并将读取到的数据存入 Message,然后 mHandler.obtainMessage(READ_DATA, bytes, -1, buffer).sendToTarget();换成 mHandler.sendMessage()
文章中提到的解决方案是修改/etc/security/limits.conf文件,在文件末尾添加如下设置并重新打开窗口运行程序
*代表所有用户

* soft nofile 655350
* hard nofile 655350

我分别仅设置

* soft nofile 5000

或者

* hard nofile 5000

发现真正受影响的参数的设置是后者-硬限制
其实这也正跟软硬限制的区别符合。

日常排查:

#查看当前系统打开的文件数
cat /proc/sys/fs/file-nr
#监控当前系统打开的文件数(每1秒更新一次)
watch -n 1 cat /proc/sys/fs/file-nr
#查看打开进程打开的文件数(倒叙)
lsof -n|awk '{print $2}'|sort|uniq -c|sort -nr|more
#根据lsof -n|awk '{print $2}'|sort|uniq -c|sort -nr|more取排在最前的进程,进而得到是哪个进程的具体描述,如下例子是1612进程
ps aux|grep 1612
#可结合下面的命令分析
#查看操作系统给改进程的硬限制值分析
cat /proc/1612/limits
#查看进程持有的句柄数,若值大于cat /proc/1612/limits中的设置,基本可以确定问题所在
ls  /proc/1612/fd/|wc -l
#查看进程持有的句柄数,若值大于cat /proc/1612/limits中的设置,基本可以确定问题所在
cat /proc/1612/limits |grep "open"

虽说上面的Linux操作系统级别的调优可以解决,但是我们首先更应该关注的是业务代码是否编写合理,就比如我上面的代码块,并没有资源关闭(为了极限测试)。否则,即使调优了,那也只会白白浪费资源。

其他参考命令:

查看当前系统支持打开的最大句柄数:more /proc/sys/fs/file-max
统计各进程打开句柄数:lsof -n|awk{print $2}|sort |uniq -c|sort -nr
统计各用户打开句柄数:lsof -n|awk{print $3}|sort |uniq -c|sort -nr
统计各命令打开句柄数:lsof -n|awk{print $1}|sort |uniq -c|sort -nr
查看当前进程实时打开的文件数:lsof -p 进程PID | wc -l
查看某个进程的句柄数限制:cat /proc/进程ID/limits
查看系统限制的最大文件打开数:cat /proc/sys/fs/file-max
查看系统当前已使用的文件句柄数:cat /proc/sys/fs/file-nr

参考
参考
参考


http://www.ppmy.cn/embedded/115802.html

相关文章

PHP、Java等其他语言转Go时选择GoFly快速快速开发框架指南

概要 经过一年多的发展GoFly快速开发框架已被一千多家科技企业或开发者用于项目开发&#xff0c;它的简单易学得到其他语言转Go首选框架。且企业版的发展为GoFly社区提供资金&#xff0c;这使得GoFly快速框架得到良好的发展&#xff0c;GoFly技术团队加大投入反哺科技企业和开…

Springboot多种请求参数

Springboot中有多种请求参数&#xff1a;简单参数、实体对象参数、数组、集合参数、日期时间参数、json参数……下列代码为每一种参数都写了一个简单的例子 package com.wzb;import com.wzb.pojo.Student; import com.wzb.pojo.User; import org.springframework.format.annot…

网络模型的保存与读取

文章目录 一、模型的保存二、文件的加载三、模型加载时容易犯的陷阱 一、模型的保存 方式1:torch.save(vgg16, “vgg16_method1.pth”) import torch import torchvision.modelsvgg16 torchvision.models.vgg16(pretrainedFalse) torch.save(vgg16, "vgg16_method1.pth…

在线文档搜索服务测试报告

目录 1. 项目背景: 2. 项目功能: 3. 测试计划: 1. 项目背景: 1.1 在线搜索服务的前端主要一下几个功能, 分别是进入搜索引擎界面(有提示输入关键词信息); 进行输入关键词的界面, 以及显示有关关键词的文档url, 点击跳转至目标文档的界面; 1.2 该在线搜索服务的文档可以实现用…

指针修仙之实现qsort

文章目录 回调函数什么是回调函数回调函数的作用 库函数qsort使用qsort函数排序整形使用qsort函数排序结构体 qsort函数模拟实现说明源码and说明 回调函数 什么是回调函数 回调函数就是⼀个通过函数指针调⽤的函数。 如果你把函数的指针&#xff08;地址&#xff09;作为参数…

如何进入电脑BIOS

前言 在日常使用电脑的过程中&#xff0c;有时我们需要进入BIOS&#xff08;基本输入输出系统&#xff09;来调整设置&#xff0c;比如更改启动顺序、调整系统日期时间或是优化硬件配置。BIOS是计算机启动时最先运行的程序之一&#xff0c;它位于主板上的一个ROM芯片中。下面&…

【监控】【Nginx】使用 Prometheus + Grafana 监控 Nginx

目录 一、什么是 Prometheus 和 Grafana&#xff1f;二 、准备工作步骤 1&#xff1a;安装 Prometheus1. 下载并解压 Prometheus2. 编辑 Prometheus 配置&#xff08;prometheus.yml&#xff09;3. 启动 Prometheus 步骤 2&#xff1a;安装 Grafana1. 安装 Grafana2. 启动 Graf…

Python ORM 框架 SQLModel 快速入门教程

创建模型 import sqlmodel import typingclass Hero(sqlmodel.SQLModel, tableTrue):id: typing.Optional[int] sqlmodel.Field(defaultNone, primary_keyTrue)name: strreal_name: strage: typing.Optional[int] None创建表 import sqlmodel import typingclass Hero(sqlm…