现象
之前用k8s集群启动了一款中间件内部依赖es做数据存储,查看日志发现es报错"Too many open files
解决办法
进入容器中执行ulimit -a
查看当前用户的文件句柄限制 发现是满足需求的,那么问题就只可能是出现在宿主机上了,执行cat /etc/sysctl.conf
查看句柄数配置,如下:
[root@test-node-01 ~]# cat /etc/sysctl.conf
vm.max_map_count=262144
fs.file-max=65536
65536
远比日志报错的104857
小,接下来就是修改宿主机的句柄数了, 有两种修改方式一种是修改单个进程的文件另一种就是修改系统配置
- 修改单个进程的文件句柄数
要查看一个进程可以打开的文件句柄数,可以通过cat /proc/<pid>/limits
查看, 要动态修改一个进程的限制,可以使用prlimit命令,具体用法为:prlimit --pid ${pid} --nofile=102400:102400
文件数可以自己定义.
对于es 容器来说, 可以执行ps -ef |grep elasticsearch
查找es进程的pid,我的进程pid为23571
.执行prlimit --pid 23571 --nofile=104857
就将23571
进程的文件句柄数修改成了104857
- 修改系统配置
- 修改
/etc/sysctl.conf
文件下面的fs.file-max
参数,行sysctl -p
并退出shell生效, 不过最好重启服务器,要不有些占用不会释放。 - 或者修改
/etc/security/limits.conf
配置文件
cat /etc/security/limits.conf
* soft nproc 655350
* hard nproc 655350
* soft nofile 655350
* hard nofile 655350
- 具体这个值应该设置成多少?
优先级(Open File Descriptors):soft limit
<hard limit
<kernel
<实现最大file descriptor数采用的数据结构
所导致的限制
其实这个值倒是没有具体限制,但是分配的值如果太大反而会影响系统性能,所以要根据具体应用调配权衡。/etc/security/limits.conf
是属于用户级别的句柄数限制而/etc/sysctl.conf
是属于系统级别的内核参数
其他
查看系统总限制 命令:cat /proc/sys/fs/file-max
查看整个系统目前使用的文件句柄数量命令:cat /proc/sys/fs/file-nr
文件句柄是用来干嘛的
句柄当做一个人的名字,并"可以通过名字(句柄),实现对句子的引用和访问",感觉这种比喻好像贴近,但问题是可能有许多人叫同一个名字,但句柄所以有意义正因为它具有唯一性,
所以这种比喻也有问题,如果换个说法,说句柄是表示你的进程与外界的i/o连接,把它当作是一个连接的名字是不是更恰当些? 文件句柄是一个十六位长度的二进制代码(Windows95后为32位无符号整数),
代表一个已被打开文件的通道号,借助于这个句柄,你的应用程序即可使用这个相应的句柄对文件进行随意存取操作,说白了文件句柄其实是一串代表着特殊含义的号码;
当然其实系统是用句柄与一些资源联系起来的,当由系统管理,动态分配给你应用程序的某些资源的代号,你就可以使用句柄访问相应的资源了,尤其在Windows系统中,有很多东东都使用句柄,如窗口,socket。
简单看来程序通过句柄获得资源的引用,来进行资源的打开和关闭的操作。
为什么会出现文件句柄耗尽的情况
主要是因为linux在文件句柄的数目上有两个级别的限制。一个是系统级别的总数限制,一个是针对用户的限制。默认情况下每个用户所能使用的句柄数是1024。一般情况下1024也够用了,但是在大容量的系统上,特别是会频繁使用网络通信和文件IO的系统上,1024很快就被耗光了。所以首先我们要调整这个值。
参考
日志抛出大量Too Many Open Files的异常Too many open files的四种解决办法