Bug:Too many open files【ulimit限制】

Bug:Too many open files

今天在开发某个下载功能时,发现文件总是下载到250多个程序就挂掉,同时会打崩服务器,查看错误日志发现报:too many open files.

  • 思路:根据错误信息可以知道打开的文件数过多,立马想到系统自身有一个ulimit限制(限制打开的文件数),可能是因为自身并发数设置过高且ulimit配置的允许打开文件数数值过低。

1 排查思路

1.1 查看ulimit数值

以Mac系统为例。

bash 复制代码
# 执行命令查看ulimit限制
launchctl limit
#第一列为项的名称,第二列为软件限制,第三列为硬件限制

如果是ulimit配置太小,可以通过下面命令修改
注意:如果数值设置的太高会影响系统的稳定性。

bash 复制代码
sudo launchctl limit maxfiles 1024 unlimited
#修改完后,open files的限制就到1024了

我将文件描述符修改到1024后,发现文件下载到1024左右程序就会卡死,可以确定和ulimit数没有关系。

1.2 查看程序并发数

查看是否是程序的并发数设置的太多(线程数或协程数),如果自身电脑打开的程序或者应用过多且并发数设置的过多,会导致某一段时间,打开的文件数超过ulimit的限制。

  • 后来查看代码,发现协程数为5,对于该系统来说并不算高

1.3 查看文件流是否关闭

因为程序是下载功能,所以需要读取服务端的文件,这个时候就需要考虑是否是打开的文件流没有关闭导致文件句柄一直没有释放。

bash 复制代码
# 查看进程号
ps -ef | grep downloader
# 根据进程id查看进程占用的文件句柄
sudo lsof -p 30794
# 查看所有已建立或者listen状态的连接
sudo lsof -i -P | grep -i "listen\|established"

执行上面命令后发现我程序一直占用这Socket没有释放,这个时候就基本可以确定是代码某处打开的文件流没有关闭。

经过review代码,排查发现是在GetS3Object的时候没有对object的Body做close操作。添加上后,问题解决。

go 复制代码
	object, err := client.GetObject(context.TODO(), &s3.GetObjectInput{
		Bucket: aws.String(bucketName),
		Key:    aws.String(key),
	})
	defer object.Body.Close()

2 解决

①修改系统ulimit参数值

以Mac系统为例。

bash 复制代码
# 执行命令查看ulimit限制
launchctl limit
#第一列为项的名称,第二列为软件限制,第三列为硬件限制

如果是ulimit配置太小,可以通过下面命令修改
注意:如果数值设置的太高会影响系统的稳定性。

bash 复制代码
sudo launchctl limit maxfiles 1024 unlimited
#修改完后,open files的限制就到1024了

②修改程序并发数

降低线程或协程数

③review代码是否有io流未关闭

我的问题是因为在获取S3对象时,忘记对object.Body做close操作

go 复制代码
=object, err := client.GetObject(context.TODO(), &s3.GetObjectInput{
	Bucket: aws.String(bucketName),
	Key:    aws.String(key),
})
defer object.Body.Close()
相关推荐
颜酱9 分钟前
# 02 | 搭骨架:用 LangGraph 编排 12 步工作流(思路)
前端·人工智能·后端
颜酱10 分钟前
02 | 搭骨架:用 LangGraph 编排 12 步工作流
前端·人工智能·后端
嘉伟桑1 小时前
Python调用电价API返回JSON示例:分时电价、现货电价和字段解析
后端
武子康1 小时前
Shippy:确定性工具、会话级 Sandbox 与 Live-Data Eval(4 类收敛 + 7 步实现方案 + 6 类评测指标)
前端·人工智能·后端
尸僵打怪兽2 小时前
Claude-code命令行无法下载插件
bug·插件·claude-code
我叫黑大帅2 小时前
我为什么单一消费者的场景下,要用 Redis List 当消息队列?
redis·后端·面试
AskHarries2 小时前
文件上传系统
后端
止语Lab3 小时前
好的 DX 不等于少写代码——三种语言的摩擦力设计课
后端
吃饱了得干活3 小时前
别再手动解析 LLM 输出了!LangChain 四种结构化输出方案对比
后端·python·langchain
程序员天天困3 小时前
Arthas trace 命令怎么用?一行定位最慢那行代码
jvm·后端