美文网首页Linux
Linux 操作系统中nproc的作用,何时修改?,查看某用户打

Linux 操作系统中nproc的作用,何时修改?,查看某用户打

作者: 前浪浪奔浪流 | 来源:发表于2022-07-05 21:50 被阅读0次

    nproc是操作系统级别对每个用户创建的进程数的限制,在Linux下运行多线程时,每个线程的实现其实是一个轻量级的进程,对应的术语是:light weight process(LWP)。怎么知道一个用户创建了多少个进程呢,默认的ps是不显示全部进程的,需要‘-L' 才能看到所有的进程。

    查看所有用户创建的进程数,使用命令:

    # ps h -Led -o user | sort | uniq -c | sort -n
          1 chrony
          1 dbus
          1 libstoragemgmt
          1 nobody
          2 avahi
          5 nginx
          6 polkitd
         10 memcached
         27 mysql
       1071 root
    

    查看root用户创建的进程数,使用命令:

    # ps -o nlwp,pid,lwp,args -u root | sort -n
    NLWP   PID   LWP COMMAND
    1    27    27 [migration/3]
    1  2828  2828 /sbin/dnsmasq --conf-file=/var/lib/libvirt/dnsmasq/default.conf --leasefile-ro --dhcp-script=/usr/libexec/libvirt_leaseshelper
    1    28    28 [ksoftirqd/3]
    1  2902  2902 nginx: master process /usr/local/nginx/sbin/nginx -c /usr/local/nginx/conf/nginx.conf
    134 26155 26155 /usr/local/jdk1.8.0_11/bin/java -server -jar /usr/local/tomcat/school/school666.jar --spring.profiles.active=test
    180 26330 26330 /usr/local/jdk1.8.0_11/bin/java -server -jar /usr/local/tomcat/smsy/school777.jar --spring.profiles.active=test
    199 25967 25967 /usr/local/jdk1.8.0_11/bin/java -server -jar /usr/local/tomcat/bulu/bulu888.jar --spring.profiles.active=test
    250 25780 25780 /usr/local/jdk1.8.0_11/bin/java -server -jar /usr/local/tomcat/private/private999.jar --spring.profiles.active=test
    

    当日志出现以下情况中的一种时,需要修改nproc:

    1. Cannot create GC thread. Out of system resources

    2. java.lang.OutOfMemoryError: unable to create new native thread

    (1)

    ps -u produser –f
    

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

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


    image.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,如下所示:
    
    image.png

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

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

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


    image.png

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


    image.png

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


    image.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的值。

    linux max_threads参数计算

    内核threads线程数是一定的,具体是跟机器内存有关系
    部分参数获取方法
    PAGE_SIZE:getconf PAGE_SIZE 单位byte 页的大小 4096即4K
    THREAD_SIZE:ulimit -s 8192 线程栈大小,单位byte 即8K

    额定具体计算如下
    max_threads = mempages / (THREAD_SIZE/PAGE_SIZE) / 8

    mempages是物理内存页的个数;
    mempages计算
    mempages = 物理内存大小 ÷ PAGE_SIZE

    例如:32G内存
    mempages = 32174 * 1024 * 1024/4*1024 = 8236544 物理内存页的个数

    max_threads = 8236544/(81024)/(41024)/8 = 514784

    因为为了保证每个用户进程总数不至于超过一半内存fork_init()指定:
    init_task.rlim[RLIMIT_NPROC].rlim_cur = max_threads/2;
    init_task.rlim[RLIMIT_NPROC].rlim_max = max_threads/2;

    即物理额定线程数为514784/2=257392

    链接:https://www.jianshu.com/p/3726af3c9771

    原文链接:
    https://blog.csdn.net/odailidong/article/details/50561257
    https://www.sohu.com/a/168794256_151779

    相关文章

      网友评论

        本文标题:Linux 操作系统中nproc的作用,何时修改?,查看某用户打

        本文链接:https://www.haomeiwen.com/subject/rotebrtx.html