Java进程内线程数量限制的相关学习
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进程内线程数量限制的相关学习的更多相关文章
- Java并发包——线程安全的Map相关类
Java并发包——线程安全的Map相关类 摘要:本文主要学习了Java并发包下线程安全的Map相关的类. 部分内容来自以下博客: https://blog.csdn.net/bill_xiang_/a ...
- Java并发包——线程安全的Collection相关类
Java并发包——线程安全的Collection相关类 摘要:本文主要学习了Java并发包下线程安全的Collection相关的类. 部分内容来自以下博客: https://www.cnblogs.c ...
- 【python之路36】进程、线程、协程相关
线程详细用法请参考:http://www.cnblogs.com/sunshuhai/articles/6618894.html 一.初始多线程 通过下面两个例子的运行效率,可以得知多线程的速度比单线 ...
- Java 进程和线程
进程和线程 在并发编程中,有两个基本的执行单元:进程和线程.在Java编程语言中,通常并发编程主要与线程有关.但是进程也很重要. 计算机系统通常具有许多活动的进程和线程.即使在只有一个执行核心,因此在 ...
- java进程和线程的区别
什么是进程,什么是线程系统要做一件事,运行一个任务,所有运行的任务通常就是一个程序:每个运行中的程序就是一个进程,这一点在任务管理器上面可以形象的看到.当一个程序运行时,内部可能会包含多个顺序执行流, ...
- Java进程和线程关系及区别
1.定义 进程是具有一定独立功能的程序关于某个数据集合上的一次运行活动,进程是系统进行资源分配和调度的一个独立单位. 线程是进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基 ...
- [Java]进程与线程的区别(转)
线程是指进程内的一个执行单元,也是进程内的可调度实体. 与进程的区别: (1)地址空间:进程内的一个执行单元;进程至少有一个线程;它们共享进程的地址空间;而进程有自己独立的地址空间; (2)资源拥有: ...
- Java—进程与线程
进程与线程 进程是程序(任务)的执行过程,具有动态性:持有资源(共享内存.共享文件)和线程,是资源和线程的载体. 线程是系统中最小的执行单元,同一进程中有多个线程,线程共享进程的资源. 线程的交互,交 ...
- Java进程与线程的区别
每个进程都独享一块内存空间,一个应用程序可以同时启动多个进程.比如浏览器,打开一个浏览器就相当于启动了一个进程. 线程指进程中的一个执行流程,一个进程可以包含多个线程. 每个进程都需要操作系统为其分配 ...
- java - 进程和线程的区别及联系
1. 进程 (1)进程主要有两个特征: a. 进程是一个实体,占有一定的地址空间.每一个进程都有它自己的地址空间,一般情况下,包括文本区域(text region).数据区域(data region) ...
随机推荐
- 在Windows操作系统中,使用powershell脚本批量删除、批量替换文件名
比如我们下载的mp3文件或者小说.评书里都带很多作者.网站等信息,如何批量一键删除掉多余的字段呢? 下面举例:批量删除文件名称 可以看到原文中,所有文件名中均包含"小番茄与火龙果-" ...
- 【OpenCV】在 Mac OS 上使用 EmguCV
前言 OpenCV是一个基于Apache2.0许可(开源)发行的跨平台计算机视觉和机器学习软件库,它具有C++,Python,Java和MATLAB接口,并支持Windows,Linux,Androi ...
- 对比Spring Boot中的JdbcClient与JdbcTemplate
本文我们一起看看Spring Boot中 JdbcClient 和 JdbcTemplate 之间的差异. 以下内容使用的Java和Spring Boot版本为: Java 21 Spring Boo ...
- VSCode C++开发环境配置: LLVM clang clangd
工欲善其事,必先利其器 llvm/clang 比 VSCode 自带的代码提示功能速度更快,功能更强(支持 clang-tidy). 安装 llvm.clang sudo apt install ll ...
- 编写一个小而强大的 Windows 动态屏保壁纸
写在前面 两年前我做了第一个开源软件 DreamScene2 动态桌面,如今受到了很多人的喜欢,这增加了我继续做好开源软件的信心.之前的这个软件一直有人希望我加入一个设置屏保壁纸的功能,因为 Drea ...
- 技术实践丨GaussDB(DWS)运维管理功能“升级”的原理和使用
摘要:本文将详细介绍GaussDB(DWS)重要运维管理功能"升级"的原理和使用. 运维管理模块是任何软件产品最基础和重要的一部分.是软件产品的门户,也是用户接触和使用软件产品的和 ...
- 从零开始学习python | 实例讲解如何制作Python模式程序
摘要:在本文中,我们将学习python中的各种模式程序. Python编程语言很容易学习.易于语法实现的各种库使其脱颖而出,这是它成为本世纪最流行的编程语言的众多原因之一.虽然学习很容易,但访问员通常 ...
- GaussDB(DWS)发生数据倾斜不要慌,一文教你轻松获取表倾斜率
摘要:GaussDB(DWS)是MPP并行架构,若表的数据存在倾斜情况,会引起一系列性能问题,影响用户体验,严重时可能会引起系统故障.因此能快速获取倾斜的表并整改是GaussDB(DWS)运维管理人员 ...
- 数字化转型鸿沟如何消除?ROMA Connect融合集成,联接企业应用现在与未来
摘要:ROMA Connect平台正在以"联接和融合"的方式,重塑传统企业上云的路径--"条条大路"通向云端. 本文分享自华为云社区<[大厂内参]第13期 ...
- nodejs升级到最新LTS版本方法汇总:linux/mac/window—npm/yum/ssh
nodejs不同版本的差异还是蛮多的,比如obj?.a 在nodejs12是不支持的,必须得升级到14才可以.但是centos yum 默认安装的,或者系统集成的nodejs版本都是很老的.项目上传到 ...