进程守护工具: Supervisor 启动下的服务,Too many open file 错误的限制

2,748 阅读4分钟

作者:林冠宏 / 指尖下的幽灵。转载者,请: 务必标明出处。

掘金:juejin.cn/user/178526…

博客:www.cnblogs.com/linguanh/

GitHub : github.com/af913337456…

腾讯云专栏: cloud.tencent.com/developer/u…


目录

  • 前序
  • 核心内容
  • 正文开始
  • Supervisor下的服务
  • 查看Supervisor下的服务文件句柄数
  • 修改方案

前序

距离上次发文章,已然一年多。并不是没再写技术文章,只不过大部分写在草稿,没发出而已。期间完成了自己的 第二本 技术类书籍:《区块链DApp开发: 基于以太坊和比特币公链》

本次文章要分享的内容是一个在后端服务中易见且原因比较隐蔽的问题:Too many open file 文件句柄打开错误。

核心内容

服务A是使用 Supervisor 启动的时候,满足下面其一条件,那么系统设置的最大文件句柄数(max open file descriptors) 将不会生效到服务A

  1. Supervisor不是使用 root 用户启动的;
  2. Supervisor 启动之后,再修改服务器系统配置。
解决方法之一
  1. 先,修改服务器系统的最大文件句柄数,教程见网上其他文章;
  2. 1的基础上,修改 Supervisor 启动时的 supervisord.conf 配置文件,在[supervisord] 栏目下添加:minfds={数字},比如下面这样:
    [supervisord]
    ...
    minfds=102400
    ...
    
  3. 重启 supervisor。

本文的核心内容就如上所述了,下面进入说教环节。

正文开始

如果你是一名后端同学,且还没遇到过 Too many open file 错误,那么原因有可能是下面的:

  1. 服务请求量不够多;
  2. 服务早期就做了多机器负载均衡;
  3. 服务没部署在 Linux 机器;
  4. 同事帮你做了处理;
  5. ...

网上关于这个错误的一般处理方法已经很多,但是在附加条件下谈这个问题的比较少。一旦出现问题,我们网络搜索解决方案的时候,往往是直接在浏览器输入关键信息,也就是直接的错误信息,比如:

搜:`Too many open file`
和搜:`Supervisor Too many open file`

往往是一字之差,就可以天差地别,所以说它易见且原因比较隐蔽,因为难于搜到一针见血的相关文章。

这里简单说说 Too many open file,部署在 Linux 机器上的服务,需要遵循 Linux 的规则:

  1. 在 Linux 系统中,所有的事物或资源,都是以文件的形式存在,比如消息、共享内存、连接等,句柄可以理解为指向这些文件的指针;
  2. 对于这些句柄,Linux 是有数量限制的,单个进程可以打开的句柄数,有上限;
  3. 所启动的服务中,当进程企图要打开的句柄已经达到了上限,抛出错误Too many open file

Supervisor下的服务

Supervisor 是著名的进程守护工具程序。我们用到它的功能很多情况下只有这么一个:当服务程序因某些原因 panic 时,而自动拉起程序,重新运行,基于这个功能,进行系列参数的定义。

由于 supervisor 的进程管理机制,它会作为父进程 fork 出子进程,也就是使用者在配置文件中指定的服务进程,比如下面的例子:

# my_server.conf
[program:my_server]
command=/home/server/my --config=""
...

my_server 最终会运行在 Supervisor 的子进程中,鉴于父子关系,my_server所在进程能允许打开的最大文件数不能超过父进程 (Supervisor) 的阈值限制。可知,若不依赖 Supervisor 启动服务,也就没这个阈值限制了。

如果我们下载的 Supervisor 版本,在原来的启动配置文件supervisord.conf文件中没有指定minfds参数,且启动用户不是 root 用户,那么最多打开的文件数目就是默认的1024 (default)。这里的结论来于文档备注:

The minimum number of file descriptors that must be available before supervisord will start successfully. A call to setrlimit will be made to attempt to raise the soft and hard limits of the supervisord process to satisfy minfds. The hard limit may only be raised if supervisord is run as root. supervisord uses file descriptors liberally, and will enter a failure mode when one cannot be obtained from the OS, so it’s useful to be able to specify a minimum value to ensure it doesn’t run out of them during execution. These limits will be inherited by the managed subprocesses. This option is particularly useful on Solaris, which has a low per-process fd limit by default

根据上面文档,可知如果不是 root 用户启动的 Supervisor,那么可以设置 minfds 参数来加大文件句柄数限制。此外,当是 root 用户启动的 Supervisor,它提到可以提高 (raised if supervisord is run as root),至于是不是提高到和系统所配置的一样,没直接说明,措辞有所隐瞒,可能是故意的,就是想你动手试试,观察得出结论。

查看Supervisor下的服务文件句柄数

要看一个依赖 Supervisor 启动的服务实际所能打开的最大文件句柄数,不要靠 ulimit 系列命令,这个是看系统的。走下面的步骤查看:

  1. ps 一下程序名称,比如:ps -ef|grep xxx;
  2. 得到 xxx 的进程号:{PID};
  3. cat /proc/{PID}/limits;
  4. 观察屏幕输出即可

修改方案

见上面 核心内容 小节