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) ...
随机推荐
- 轻量对象存储 LighthouseCOS 用户实践征文
产品使用攻略.上云技术实践,有奖征集,多重好礼等您带回家- 存储桶一键挂载轻量应用服务器,简单易用,腾讯云轻量对象存储用户实践征文活动特惠:腾讯云轻量云专场特惠活动. 投稿说明 注册/登录腾讯云账号, ...
- K8s和声明式编程
转载:原文链接 认识k8s之后,他的操作模式对我来说是一种很不错的体验.他提供了更接近现实世界的面向对象接口. 什么是k8s? Kubernetes(K8s)是一种开源容器编排平台,用于自动化部署.扩 ...
- grafana_mysql安装
https://dl.grafana.com/oss/release/grafana-5.4.0-1.x86_64.rpm #官网下载安装包 [root@zbx4_0 source]# rpm -iv ...
- 一颗红心,三手准备,分别基于图片(img)/SCSS(样式)/SVG动画实现动态拉轰的点赞按钮特效
华丽炫酷的动画特效总能够让人心旷神怡,不能自已.艳羡之余,如果还能够探究其华丽外表下的实现逻辑,那就是百尺竿头,更上一步了.本次我们使用图片.SCSS样式以及SVG图片动画来实现"点赞&qu ...
- Materialize MySQL引擎:MySQL到Click House的高速公路
摘要: MySQL到ClickHouse数据同步原理及实践 引言 熟悉MySQL的朋友应该都知道,MySQL集群主从间数据同步机制十分完善.令人惊喜的是,ClickHouse作为近年来炙手可热的大数据 ...
- JVM面试必问:G1垃圾回收器
摘要:G1垃圾回收器是一款主要面向服务端应用的垃圾收集器. 本文分享自华为云社区<JVM面试高频考点:由浅入深带你了解G1垃圾回收器!!!>,原文作者:Code皮皮虾 . G1垃圾回收器介 ...
- 小熊派:用OpenHarmory3.0点亮LED
摘要:作为一个代表性的完整的开发,本案例可以分成3大部分:代码文件的规划,LED灯的驱动开发,点亮LED的业务开发. 本文分享自华为云社区<在小熊派Micro上用OpenHarmory3.0点亮 ...
- Markdown Emojio 表情图标
:smile: :laughing: :blush: :smiley: ️ :relaxed: :smirk: :heart_eyes: :kissing_heart: :kissin ...
- BBS项目(三):侧边栏筛选功能 文章详情页搭建 点赞点踩功能 文章根评论功能
目录 复习与补充 侧边栏筛选功能 文章详情页搭建 点赞点踩样式搭建 点赞点踩功能完善 文章评论前期准备 文章根评论业务逻辑 练习 复习与补充 admin后台管理复习: admin.py文件中注册模型表 ...
- CS01 BOM客制化屏幕增强
一.BOM行项目新增定制字段 效果如下 二.前台增强实现步骤 1.行项目表新增字段 2.CMOD,增强项目PCSD0002:在行项目中增强(PCSD0003:在抬头增强) 3.双击创建定制化屏幕 4. ...