现象

之前用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

  • 修改系统配置

    1. 修改/etc/sysctl.conf文件下面的fs.file-max参数,行sysctl -p 并退出shell生效, 不过最好重启服务器,要不有些占用不会释放。
    2. 或者修改/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的四种解决办法

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐