缘起(原因)

最近由于公司业务,在一台服务器上添加10个分站,由于网站访问量上来,网站的打开文件过多,网站出现偶发性500错误
服务器代码截图
查看服务器日志发现

2023/05/26 16:16:46 [alert] 1581#1581: *1656270 socket() failed (24: Too many open files) while connecting to upstream, client: 120.27.78.73, server: bj.bjpowernode.com, request: "GET /prospect/web/ HTTP/1.1", upstream: "fastcgi://127.0.0.1:9000", host: "bj.bjpowernode.com", referrer: "https://bj.bjpowernode.com/prospect/"

google搜索的解决方案如下

解决方案

查看max open files

查看nginx的 max open files:

grep 'open files' /proc/$(cat /usr/local/openresty/nginx/logs/nginx.pid)/limits

查看linux系统限制命令

你可以使用ulimit命令来查看系统文件限制。

ulimit -Hn
ulimit -Sn

ulimit -Hn 是一个命令行命令,可以用来查看当前系统用户所能打开的最大文件描述符数量的硬限制。文件描述符是操作系统为了表示和操作文件而提供的一种机制,每个文件描述符都是一个非负整数,用来标识打开的文件或者管道。

-H 参数表示显示硬限制(hard limit),即系统管理员为当前用户设置的最大限制值。-n 参数表示显示文件描述符数量。通常情况下,硬限制是软限制(soft limit)的上限,也就是可以修改的最大。

-S 参数表示显示软限制(soft limit),即当前用户可以打开的文件描述符数量的默认值。-n 参数表示显示文件描述符数量。

软限制是当前用户可以打开的文件描述符数量的默认值,用户可以通过 ulimit -n 命令来查看和修改软限制。通常情况下,硬限制是软限制的上限,也就是可以修改的最大值。

如果想要修改软限制,一般可以使用 ulimit -n 命令进行修改。需要注意的是,软限制不能超过硬限制。如果软限制超过了硬限制,那么修改软限制时会失败。

在nginx服务器可以打开的文件数量受你操作系统的限制,编辑/etc/sysctl.conf 在尾部追加如下内容:

fs.file-max = 6553560

保存退出,从新读取系统配置

sysctl -p

fs.file-max 是一个系统级别的参数,表示整个系统可以同时打开的文件描述符的最大数量。它的值是系统启动时内核根据系统配置自动确定的,并且通常比 /proc/sys/fs/nr_open 的值要大。

再编辑 /etc/security/limits.conf 添加内容:

* soft nofile 1048576
* hard nofile 1048576

在Linux系统中,/etc/security/limits.conf 文件用于配置用户的资源限制,

其中包括文件描述符限制。

soft 是该文件中用户的软件文件描述符限制的一行。
hard 是该文件中用户的硬限制描述符限制的一行。

具体而言,* soft nofile 表示所有用户在软限制(soft limit)下允许打开的文件描述符的最大数量。软限制是一种限制值,表示操作系统通常会发出警告,但不会阻止用户超过该限制。与之相对,硬限制(hard limit)是一个更严格的限制值,超过该值将会被系统强制限制。

通过在 /etc/security/limits.conf 中设置 root soft nofile,可以为 root 用户指定软限制下的文件描述符数量。例如,以下是一个设置 root 用户软限制为 5000 个文件描述符的示例行:

root soft nofile 5000

这意味着系统将向 root 用户发出警告,当其打开的文件描述符数量接近 5000 时,但并不会强制阻止超过该限制。

这种配置对于管理文件描述符资源的分配和保护非常有用,可以防止某个用户或进程占用过多的文件描述符,从而影响系统的正常运行。然而,该配置只对 root 用户生效,其他用户可以通过相应的配置来设置其软硬限制的文件描述符数量。

* hard nofile 1048576 表示设置所有用户(通配符 *)在硬限制(hard limit)下可以打开的文件描述符的最大数量为 1048576。

hard limit 是一种严格的资源限制,超过该限制的用户或进程将无法继续增加资源的使用。在这种情况下,nofile 代表文件描述符的数量限制。

通过配置 * hard nofile 1048576,这意味着系统为所有用户设定了硬限制,其中任何用户或进程无法超过 1048576 个文件描述符。这个值非常大,因此在实际情况中,系统几乎不会达到这个限制。

该设置的目的是确保系统中的所有用户都受到较高的文件描述符限制,以满足应用程序的需求。这对于需要大量并发文件处理的系统或服务非常重要,例如网络服务器或数据库服务器。

需要注意的是,limits.conf 文件中的软限制(soft limit)和硬限制(hard limit)可以有不同的值。软限制是一个警告阈值,而硬限制是一个强制限制,超过该限制会导致操作系统拒绝进一步的资源分配。

修改nginx的配置

还有一种可能就是nginx进程自身的默认配置打开文件的数据额太少。

修改worker_rlimit_nofile配置

nginx中的worker_rlimit_nofile选项用于指定每个工作进程可以拥有的最大打开文件描述符(文件句柄)数量。它在每个工作进程的基础上设置文件描述符的资源限制。

worker_processes  16;

worker_rlimit_nofile 655350;

events {
    use epoll;
    worker_connections  65535;
}

个人觉得要多开了进程来承接外来请求、以前的服务器进程是8个,现在添加到了16个。worker_rlimit_nofile的值也给到了655350。查看了/proc/sys/fs/nr_open的值,只要小于这个值就合理。

/proc/sys/fs/file-max/proc/sys/fs/nr_open 都涉及文件描述符的限制,但它们有一些区别。

/proc/sys/fs/file-max 是一个系统级别的参数,表示整个系统可以同时打开的文件描述符的最大数量。它的值是系统启动时内核根据系统配置自动确定的,并且通常比 /proc/sys/fs/nr_open 的值要大。

/proc/sys/fs/nr_open 则是一个进程级别的参数,表示单个进程可以同时打开的文件描述符的最大数量。它的值是一个上限,所有进程的文件描述符数总和不应超过该值。

通常情况下,/proc/sys/fs/nr_open 的值应小于 /proc/sys/fs/file-max 的值。这是因为文件描述符分配给进程时,受到 /proc/sys/fs/nr_open 的限制。而 /proc/sys/fs/file-max 是整个系统的文件描述符限制,它包含了所有进程的限制之和。

如果需要增加系统的文件描述符限制,可以通过修改 /proc/sys/fs/nr_open/proc/sys/fs/file-max 中的值来实现。通常情况下,应先适当增加 /proc/sys/fs/nr_open 的值,然后再相应地增加 /proc/sys/fs/file-max 的值,以确保进程级别的限制不超过系统级别的限制。

需要注意的是,修改这些值需要具有 root 或管理员权限,并且在调整时应慎重操作,以避免对系统的性能和稳定性产生负面影响。

修改limits.conf参数错误引起的问题

当时记得是修改配置文件软限制大于了硬限制后,非root权限用户登陆即退出。

通过root用户登陆,查看系统日志

May 29 10:39:35 powernode sshd[2568]: pam_unix(sshd:session): session opened for user xiaozhao by (uid=0)
May 29 10:39:35 powernode sshd[2568]: error: PAM: pam_open_session(): Permission denied
May 29 10:39:35 powernode sshd[2576]: Received disconnect from 111.201.49.115 port 37773:11: disconnected by user
May 29 10:39:35 powernode sshd[2576]: Disconnected from user xiaozhao 111.201.49.115 port 37773
May 29 10:39:35 powernode systemd[1]: session-43.scope: Succeeded.

系统中所配置的 Session 类型的 PAM 模块在验证相关状态时失败,可能原因如下:

  1. 验证 sudo 权限时失败: /etc/sudoers文件未给相关用户配置充足的权限。
  2. 验证系统资源限制的配置时失败: ulimit 命令或 /etc/security/limits.conf
    文件配置了不合理的系统资源限制。

解决办法

当原因为验证系统资源限制的配置时失败时,可按如下两种方案进行操作。

执行如下操作修改系统资源限制配置。

使用 root 用户登录操作系统。查看内核允许的进程最大打开文件数。

cat /proc/sys/fs/nr_open

进入 /etc/security/limits.conf文件,配置小于/proc/sys/fs/nr_open的文件打开数限制:

# 假设655360小于
/proc/sys/fs/nr_opencat >> /etc/security/limits.conf <<EOF* soft nofile 655360* hard nofile 655360EOF

当无法判断具体原因时,依次尝试如下方法解决问题。

当原因为验证 sudo 权限时失败时,执行如下操作给予相关用户充足的 sudo 权限。

使用 root 用户登录操作系统。

打开 /etc/sudoers 文件:

vim /etc/sudoers

修改 root 与 qidong 用户的权限,并保存文件:

root  ALL=(ALL) ALL
qidong ALL=(ALL) ALL

执行如下操作移除 PAM 在 session 中对系统资源限制的验证

注意
此方法将移除 PAM 在 session 中对系统资源限制的验证,可能引入安全风险。
此方法将在 debian/ubuntu 系统上使 ulimit 的配置不生效。

使用 root 用户登录操作系统

打开 PAM 配置文件:

vim /etc/pam.d/sudo

将以下行删除,并保存文件:

session    required     pam_limits.so
Last modification:June 8, 2023
如果觉得我的文章对你有用,请随意赞赏