内核linux soft nproc,故障案例 | 说说 Linux 操作系统中nproc的那些事

原标题:故障案例 | 说说 Linux 操作系统中nproc的那些事

众所周知,Linux操作系统中利用ulimit限制shell启动进程占用的资源,ulimit支持对用户的打开进程数、进程打开文件句柄数、进程打开文件的大小、进程coredump文件大小等资源进行限制,从而防止某个用户进程过度占用系统资源,避免影响整个操作系统和其他应用的正常运行。但是使用ulimit进行限制后,当用户资源超限制时会出现各种各样的报错,最近笔者经常遇到用户打开进程数超过限制后带来的各种问题,特来跟大家谈一谈用户打开进程数,即nproc参数。

首先咱们来看看几个故障案例:

故障案例

故障一:同学A前来报障:“赶紧帮我看看,我的应用用户今天的crontab任务没有执行!”

笔者登录主机,看了一下/var/log/cron日志,里面有报错信息:

故障二:同学B前来报障:“赶紧帮我看看,我的应用用户登录不了系统了!”

笔者登录主机,看了一下/var/log/secure日志,里面有报错信息:

故障原因

在这两个故障案例中,2份不同主机日志里均含有共同的报错信息:Resource temporarily unavailable,中文理解就是资源暂时不可用,其原因大概有3种:

1. 用户的nproc达到限制,无法创建新的进程

2. 系统没有可分配的的pid,即进程号已经达到内核参数kernel.pid_max的限制

3. 系统可用内存低,新的进程无法申请到内存导致不能启动。

在笔者遇到的生产故障中,基本上是第一种原因。现在咱们就来探讨一下用户nproc达到限制时,如何排查。

故障排查

由于是用户打开进程数达到了限制,那么排查方法主要是查看用户目前打开的进程的数量,以上面出现问题的produser用户为例:

(1)

ps -u produser –f

此方法是查看当前produser用户打开的进程数量。

但是,(1)方法在用户应用是多线程模式下不好使,使用此统计方法,统计出来的进程数量要小于限制值。那么应该如何查询,我们先来看一段官方文档 man 2 setrlimit:

e1c46cc9d481600113f87104fd823d87.png

因此在Linux主机上我们应该统计用户打开的进程线程的数量,ps命令需要加-L参数用于查看线程,所以给出下面的命令:

(2)

ps -u produser –Lf

大部分情况使(2)方法就能查看的结果。但是笔者要说的是⑵方法仍然存在问题,统计出来的进程数在某些情况下仍然小于限制值,再看一下上面的文档,其实nproc限制值是限制的real user创建的进程线程数。进程创建的时候存在real user和effective user两个属性,用ps命令统计的时候默认显示的是effective user的进程数,当进程的real user跟effective user不一致的时候会导致上面的命令统计的结果小于限制值。 上面-u参数查看的是effective user,因此这里再改进一下,使用-U参数查real user为produser的用户:

(3)

ps -U produser –Lf

这个命令也是根据实际案例发现的:我们生产上存在部分用户的crontab任务没有加标准输出和错误输出的重定向,同时系统的postfix服务没有打开,这样crontab任务输出会以邮件形式存放到/var/spool/postfix/maildrop目录,最终导致文件系统的inode使用率过高。一日我们工程师在对maildrop清理的时候不小心删除了maildrop目录,crond进程的子进程会hang住,结果用户进程数超过限制,导致其他用户应用出现问题、无法登录等问题。最开始使用的是⑵方法统计的线程数量,结果小于用户的限制值,后来发现crond进程在执行用户任务的时候会开辟一个CROND的子进程切换到对应用户执行相应的任务,其中这些CROND的子进程对应的effective user为root,real user为produser,如下所示:

f25113afe8ae4037a9c1f59e56c14a98.png

因此当我们要统计用户打开的进程线程数的任务,一定要统计real user的进程线程数,下面的方法可以正确统计主机所有用户的进程线程数:

上面主要给大家介绍了用户nproc达到限制值时分析的方法。接着给大家介绍一个案例,主要谈谈用户nproc hard的默认值是怎么取到的。

笔者一天制作了一台1C2G的RHEL6版本虚拟机,用于制作虚拟机模板,笔者在/etc/security/limits.d/90-nproc.conf修改了用户nproc的soft值,如下:

f39bfc3f30d97a7ce55b3fd72a1114b7.png

该配置设置了root用户的nproc的soft值为ulimited,其他用户的nproc的soft值为10240。然而当检查每个用户的nproc值的时候惊奇地发现用户的nproc的hard和soft值均为7387,如下:

f33c21ff8c8c35c8321fa83d03b99fd9.png

这个值很奇怪,用户nproc的soft和hard值并不是10240,但是在其他主机上这个配置能够达到预期的值。经过分析,笔者认为上面的配置中由于并没有设置用户nproc的hard值,导致用户nproc的soft值受到hard值的限制,取不到预期的值,因此关键问题需要搞清楚hard值是由哪个因素决定的。笔者琢磨了一下,认为nproc的hard值是在内核获取到的,所以翻看了内核代码,果然在内核代码fork.c中发现端倪:

95549f9282da451edbf85d3039e6646e.png

其中mempages是物理内存页的个数,PAGE_SIZE为4K,THREAD_SIZE在笔者的x86平台是16K,所以最后默认的nproc值为:

default_nproc = max_threads/2

= MemTotal(KB) / 256(KB)

即默认nproc大小取决于主机内存大小。在笔者2G内存(实际虚拟机内存为1877M,Hypervisor管理虚拟机有内存开销)的虚拟机上,计算一下:

default_nproc = 1877*1024/256 = 7508

由于kernel会占用一部分的内存,实际的nproc(本例中为7387)要比计算值稍小一些。笔者的案例中仅仅设置了用户nproc的soft值,所以用户的nproc的soft值被限制在default_nproc。因此上面例子中有两种解决方法:

1. 评估需求,用户nproc的要是少于7387的话,就降低;

2. 在配置文件中,设置上用户nproc的hard值为10240,通过提升hard值来满足预期。

因此各位看官今后要根据主机内存配置合理地设置用户nproc的值。

看更多文章可以到社区“平台人生”专栏

http://www.talkwithtrend.com/Column/detail/id/11返回搜狐,查看更多

责任编辑:

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值