Java进程内线程数量限制的相关学习


背景

还是之前出现 cannot create native thread 的问题的后续
周末在家学习了下如何在容器外抓取dump.
也验证了下能否开启超过宿主机 nofile 配置的进程数量. 想着总结一下学习到的东西, 不枉周六不午休, 周天晚上还开会到11点多.

关于线程

Linux 里面进程是资源分配的最小单元
现成是字段调度的最小单元. 实际上Linux并没有实现严格意义上的进程与线程的关系.
他实际上是一个LWP 轻量级进程的 概念来实现的线程. java启动之后 会不停地创建一些线程来干具体的工作.
有一些java自身使用, 有一些事具体业务使用的.
这里想着从系统层和java层进行一些简单的学习.

Java的线程信息

Java 启动之后其实会产生很多现成
1. Java进程号对应的线程. 这个应该是一个守护或者是单独的现成
2. 会有CPU个数的GC线程.存在. 这个与GC的算法有关系.
3. 会有一些compile的进程, 用于进行解释和编译. 而且还分为C1和C2的编译器.
4. 会有连接redis的线程, 连接数据库的线程, 以及一些logback,记录日志等的线程.
5. 计划任务的线程, 如果有的话.
6. 还有一个核心线程 比如 http 开头 tomcat 或者是 jetty的线程池 一般情况下: 这个http类似的核心线程池的数量一般是比较重要的内容.

关于http线程池的配置

很早之前研究过这个线程池
当时的想法是线程池的数量跟能够承载的并发数正相关. 跟CPU有关系, 跟网络有关系, 跟数据库有关系. CPU多了肯定能够支撑更多的线程数量.
但是不完全有CPU数量来决定.
理论上应该是
CPU数量/平均每个线程一次请求需要的时间
这个线程处理的时间. 是on CPU的时间. 要排除 网络,数据库,的请求时间.
因为线程的主动和被动的的切换是很快的 是微秒级, 每秒钟进行万级别的上下切换. 所以理论上一个CPU可以干很多事情, 这个可以类比 单线程的redis的请求处理过程. 但是理论上不要将CPU消耗的太多
建议至少留有 40%的资源用于 网络,io,系统监控, 调度等资源
也就是建议是
0.6*CPU数量/(平均每个线程一次请求需要的时间+调度损耗+切换损耗等)
保证机器不要太高的CPU导致问题.

关于线程数量的限制

Linux下线程数量的限制参数很多
通过国内最好国际最差的百度搜索引擎可以查到如下内容: stack_size
max_user_processes
sys.vm.max_map_count
sys.kernel.threads-max
sys.kernel.pid_max

分别解释为

stack_size

stack_size
是一个进程/线程重建之后建立的栈区域大小
如果值太大, 那么系统支持的栈数量就会很小,
如果值太小, 则很容易出现栈溢出的问题,导致功能不正常.
理论上机器上面能够用来存储栈的内存大小 除以 stack_size 就是可以创建进程的数量了
这个值是一个硬件限制的值, 还可能会受到其他参数的影响.

max_user_processes

max_user_processes

可以通过 ulimit -a 或者是
ulimit -u 进行查看 可以看到一个用户级别的能够打开多少个线程信息 这个值可以你在 /etc/security/limits.conf 里面进行限制.
需要注意一个配置文件的优先级:
专有的比全部的级别要高.
/etc/security/limits.d/
的优先级高于
/etc/security/limits.conf

sys.vm.max_map_count

max_map_count
会限制一个进程可以拥有的VMA(虚拟内存区域)的数量
这个参数也会间接影响进程能够创建的线程数量. 经常遇到的问题是:
报错“max virtual memory areas vm.max_map_count [65530] is too low,
increase to at least [262144]” 修改方式:
sysctl -w vm.max_map_count=262144
永久修改为:
vim /etc/sysctl.conf
vm.max_map_count=262144

sys.kernel.threads-max

该参数大致意思是,系统内核fork()允许创建的最大线程数,
在内核初始化时已经设定了此值,但是即使设定了该值,但是线程结构只能占用可用RAM page的一部分,
约1/8(注意是可用内存,即Available memory page),如果超出此值1/8则threads-max的值会减少 内核初始化时,默认指定最小值为MIN_THREADS = 20,MAX_THREADS的最大边界值是由FUTEX_TID_MASK值而约束,
但是在内核初始化时,kernel.threads-max的值是根据系统实际的物理内存计算出来的

sys.kernel.pid_max

kernel允许当前系统分配的最大PID identify,
如果kernel 在fork时hit到这个值时,
kernel会wrap back到内核定义的minimum PID identify,
意思就是不能分配大于该参数设定的值+1,该参数边界范围是全局的,属于系统全局边界

参数范围

参数名称 范围边界
kernel.pid_max 系统全局限制
kernel.threads-max 系统全局限制
vm.max_map_count 进程级别限制
/etc/security/limits.conf 用户级别限制

关于K8S模式下的限制

PodPidsLimit 参数
Kubernetes 允许你限制 Pod 中运行的进程个数。
你可以在节点级别设置这一限制, 而不是为特定的 Pod 来将其设置为资源限制。
每个节点都可以有不同的 PID 限制设置。
要设置限制值,你可以设置 kubelet 的命令行参数 --pod-max-pids,或
者在 kubelet 的配置文件中设置 PodPidsLimit 在某些 Linux 安装环境中,操作系统会将 PID 约束设置为一个较低的默认值,例如 32768。
这时可以考虑提升 /proc/sys/kernel/pid_max 的设置值。 如果资料来自官网, 需要注意如果K8S的kubelet 限制了 pid in pod
那么在达到这个limit 时 程序会提示无法 create native thread
这是在产品内部进行 执行命令时 比如 top ls 等
会提示 cannot fork 这个地方很容易出现坑, 需要云平台进行协助设置.

官方关于这个参数的解释

你可以配置 kubelet 限制给定 Pod 能够使用的 PID 个数。
例如,如果你的节点上的宿主操作系统被设置为最多可使用 262144 个 PID,
同时预期节点上会运行的 Pod 个数不会超过 250,
那么你可以为每个 Pod 设置 1000 个 PID 的预算,避免耗尽该节点上可用 PID 的总量。 如果管理员系统像 CPU 或内存那样允许对 PID 进行过量分配(Overcommit),
他们也可以这样做, 只是会有一些额外的风险。
不管怎样,任何一个 Pod 都不可以将整个机器的运行状态破坏。
这类资源限制有助于避免简单的派生炸弹(Fork Bomb)影响到整个集群的运行。

一个不是总结的总结

线程池,连接池都是为了减少资源创建和销毁需要时间开销的管理方式

但既然是一种管理, 他自就会有开销

重点在于. 管理的overhead和节约的overhead 之间的比率.
如果能够在仅仅使用 1k个CPU的cycle 进行管理的开销下能够减少 1G甚至更高的CPU开销
那么这个管理就非常值得. 所以线程池的使用 是要很慎重的
如果每次申请了线程不进行复用, 其实没有必要创建线程池.
必须复用的东西才可以进行池化的处理. 换句话说, 如果你想更高的承载客户的需求, 可以将线程池的max 设置的比较大
但是这样会导致每个人都会变慢. 一个合理的方式是在 CPU 出去必然的开销之外, 可以用于业务处理的周期内.
插空进去最多的线程数量, 就是最优秀的参数配置. 还是那句话
这个配置跟CPU的算力有关系,跟网络,跟IO,跟数据库,跟应用的业务逻辑有关系.
并没有一个放之四海而皆准的公式来进行计算.

Java进程内线程数量限制的相关学习的更多相关文章

  1. Java并发包——线程安全的Map相关类

    Java并发包——线程安全的Map相关类 摘要:本文主要学习了Java并发包下线程安全的Map相关的类. 部分内容来自以下博客: https://blog.csdn.net/bill_xiang_/a ...

  2. Java并发包——线程安全的Collection相关类

    Java并发包——线程安全的Collection相关类 摘要:本文主要学习了Java并发包下线程安全的Collection相关的类. 部分内容来自以下博客: https://www.cnblogs.c ...

  3. 【python之路36】进程、线程、协程相关

    线程详细用法请参考:http://www.cnblogs.com/sunshuhai/articles/6618894.html 一.初始多线程 通过下面两个例子的运行效率,可以得知多线程的速度比单线 ...

  4. Java 进程和线程

    进程和线程 在并发编程中,有两个基本的执行单元:进程和线程.在Java编程语言中,通常并发编程主要与线程有关.但是进程也很重要. 计算机系统通常具有许多活动的进程和线程.即使在只有一个执行核心,因此在 ...

  5. java进程和线程的区别

    什么是进程,什么是线程系统要做一件事,运行一个任务,所有运行的任务通常就是一个程序:每个运行中的程序就是一个进程,这一点在任务管理器上面可以形象的看到.当一个程序运行时,内部可能会包含多个顺序执行流, ...

  6. Java进程和线程关系及区别

    1.定义 进程是具有一定独立功能的程序关于某个数据集合上的一次运行活动,进程是系统进行资源分配和调度的一个独立单位. 线程是进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基 ...

  7. [Java]进程与线程的区别(转)

    线程是指进程内的一个执行单元,也是进程内的可调度实体. 与进程的区别: (1)地址空间:进程内的一个执行单元;进程至少有一个线程;它们共享进程的地址空间;而进程有自己独立的地址空间; (2)资源拥有: ...

  8. Java—进程与线程

    进程与线程 进程是程序(任务)的执行过程,具有动态性:持有资源(共享内存.共享文件)和线程,是资源和线程的载体. 线程是系统中最小的执行单元,同一进程中有多个线程,线程共享进程的资源. 线程的交互,交 ...

  9. Java进程与线程的区别

    每个进程都独享一块内存空间,一个应用程序可以同时启动多个进程.比如浏览器,打开一个浏览器就相当于启动了一个进程. 线程指进程中的一个执行流程,一个进程可以包含多个线程. 每个进程都需要操作系统为其分配 ...

  10. java - 进程和线程的区别及联系

    1. 进程 (1)进程主要有两个特征: a. 进程是一个实体,占有一定的地址空间.每一个进程都有它自己的地址空间,一般情况下,包括文本区域(text region).数据区域(data region) ...

随机推荐

  1. 2023-11-29:用go语言,给你一个字符串 s ,请你去除字符串中重复的字母,使得每个字母只出现一次。 需保证 返回结果的字典序最小。 要求不能打乱其他字符的相对位置)。 输入:s = “cba

    2023-11-29:用go语言,给你一个字符串 s ,请你去除字符串中重复的字母,使得每个字母只出现一次. 需保证 返回结果的字典序最小. 要求不能打乱其他字符的相对位置). 输入:s = &quo ...

  2. Kubernetes的拐点助推器:左手开源,右手边缘计算

    摘要:KubeEdge 是首个基于 Kubernetes 扩展的,提供云边协同能力的开放式智能边缘计算平台,也是 CNCF 在智能边缘领域的首个正式项目.依托 Kubernetes 强大的容器编排和调 ...

  3. 【一行代码秒上云】Serverless六步构建全栈网站

    摘要:Serverless怎么玩?听一千道一万不如亲手来实践,跟着我们以华为云Serverless实践FunctionGraph来免费体验一下六步构建全栈网站吧 前言: Serverless怎么玩?听 ...

  4. 云小课|MRS基础原理之Hudi介绍

    阅识风云是华为云信息大咖,擅长将复杂信息多元化呈现,其出品的一张图(云图说).深入浅出的博文(云小课)或短视频(云视厅)总有一款能让您快速上手华为云.更多精彩内容请单击此处. 摘要:Hudi是数据湖的 ...

  5. Nginx 四层代理配置

    四层代理比较方便.简单,nginx.conf 如下 #user nobody; worker_processes 1; #error_log logs/error.log; #error_log lo ...

  6. JAVA CRC16

    JAVA CRC16 /** * CRC-16 * * <table width="400px" border="1" cellpadding=" ...

  7. 利用GetPrivateProfileString相关函数读取配置文件(.ini)

    配置文件中经常用到ini文件,在VC中其函数分别为: 写入.ini文件: bool WritePrivateProfileString(LPCTSTR lpAppName,LPCTSTR lpKeyN ...

  8. VMware Workstation centos7 虚拟机桥接方式联网,获取动态IP

    在VMware中安装 Centos7 虚拟机,日常需要带着电脑外出.因此在远程连接虚拟机时,就要求与宿主机在同一网段.在不修改路由器的情况下,让宿主与centos7都动态从路由器获取IP地址,就能解决 ...

  9. AC(AtCoder) Library 文档翻译

    AC(AtCoder) Library Document下载使用 如何安装 首先在 Github 上找到 ac-library 仓库.下载最新版本 解压 zip 文件后将 atcoder ,放置GCC ...

  10. OS | 文件系统总结

    文件系统总结 逻辑文件面向用户,学习时应该掌握不同的逻辑文件之间的特点 目录文件时链接逻辑文件和物理文件的桥梁,学习时应该体会到目录文件时如何优化访问时间 物理文件是指文件的数据如何存储在磁盘等存储设 ...