聊聊动态线程池的9个场景(改进版)

news2025/7/21 21:58:46

线程池是一种基于 池化思想管理线程 的工具,使用线程池可以减少 创建销毁线程的开销,避免线程过多导致 系统资源耗尽。在 高并发以及大批量 的任务处理场景,线程池的使用是必不可少的。

如果有在项目中实际使用线程池,相信你可能会遇到以下痛点:

  1. 线程池随便定义,线程资源过多,造成服务器高负载。

  2. 线程池参数不易评估,随着业务的并发提升,业务面临出现故障的风险。

  3. 线程池任务执行时间超过平均执行周期,开发人员无法感知。

  4. 线程池任务堆积,触发拒绝策略,影响既有业务正常运行。

  5. 当业务出现超时、熔断等问题时,因为没有监控,无法确定是不是线程池引起。

  6. 原生线程池不支持运行时变量的传递,比如 MDC 上下文遇到线程池就 GG。

  7. 当项目关闭时,无法做到优雅退出,大量正在运行的线程池任务被丢弃。

  8. 线程池运行中,任务执行停止,怀疑发生死锁或执行耗时操作,但是无从下手。

基于以上诸多痛点,小马哥着手 hippo4j 的开发,致力于打造标准线程池 动态变更 和 监控 的中间件框架。

GitHub:https://github.com/opengoofy/hippo4j

Gitee:https://gitee.com/agentart/hippo4j

什么是 hippo4j

hippo4j 通过对 JDK ThreadPoolExecutor 线程池增强,以及扩展三方框架底层线程池等功能,为业务系统提高线上运行保障能力。

小贴士:hippo4j 不止于 Java ThreadPoolExecutor 的增强,DubboRabbitMQRocketMQHystrixTomcatJettyUndertow 等框架线程池也都有进行监控和动态变更。

什么场景适合用 hippo4j

1. 线程池随意定义,造成服务器高负载

在系统开发的过程中,因为涉及到多人协作,难免会出现信息不互通的情况。在同一个系统,对于线程池来说,常见的是线程池随意定义。

  • 开发者张三要记录用户操作日志,定义了 user-log-record-thread-pool

  • 开发者李四要记录会员操作日志,定义了 member-log-record-thread-pool

  • 开发者王五要记录权限操作日志,定义了 power-log-record-thread-pool

  • ……

随着系统不断开发,相同或不同语义的线程池被定义得越来越多,间接导致服务器资源严重耗损。

而如果系统中使用 hippo4j,能够在控制台查看当前应用已有线程池,是否存在相同语义且业务可复用线程池实例,避免线程资源过度浪费。

2. 线程池参数不易评估

业务中使用了线程池,十个程序员可能有九个都在犯嘀咕,这线程池的配置应该如何选择?

我觉得犯纠结的点主要有两个,无外乎设置的数多了或者少了。

  1. 如果预设的线程数或阻塞队列数量少了,当业务量上来,会遇到两种情况,不管哪一种对业务来说都是不能接受的。

    1. 预估 200ms 执行完的任务,可能会 2s 执行完,因为任务都在排队。

    2. 任务满了后,开始执行拒绝策略,影响正常业务。

  2. 如果超量设置线程池的参数,无疑会造成资源浪费,同样会造成两种情况。

    1. 线程资源也是占用服务器资源的,开启的多了对服务器有一定压力。

    2. 如果过多得创建线程,当和其它线程池一起执行时,服务器 CPU 上下文切换也是个问题。

大家都知道,如果要修改运行中应用线程池参数,需要停止线上应用,调整成功后再发布,而这个过程异常的繁琐,如果能在运行中动态调整线程池的参数多好。

美团技术团队基于这些痛点,推出了动态线程池的概念,催生了一批动态线程池框架,hippo4j 也是其一。

如果应用是集群部署,hippo4j 可以选择修改线程池 某一实例,或者修改 集群全部实例,运行时生效,不需要再重启服务。

再比如,压测时使用 hippo4j 动态调整线程池参数,对于开发测试来说,也是个不错的选择。

3. 线程池运行时报警策略

从线程池运行时监控的角度出发,hippo4j 内置 4 种报警策略,线程池活跃度、阻塞队列容量、拒绝策略触发以及任务运行超时报警。

  • 线程池活跃度:假设阈值设置 80%,线程池最大线程数 10,当线程数达到 8 发起报警。

  • 阻塞队列容量:假设阈值设置 80%,阻塞队列容量 100,当容量达到 80 发起报警。

  • 触发拒绝策略:当线程池任务触发了拒绝策略时,发起拒绝策略报警。

  • 任务运行超时:假设单个任务超时为 1000ms,任务执行超过该时间发起报警。

hippo4j 支持钉钉、企业微信和飞书软件通知,线程池任务运行超时报警示例:

4. 线程池运行时状态对开发者黑盒

线程池在服务运行过程中,对开发者来说是一个完全的黑盒。开发者无法得知线程池的参数变化,比如阻塞队列数量或者完成任务数等核心参数,这对于排查问题来说并不友好。

hippo4j 支持线程池运行时状态实时查看,并在核心参数的基础上扩展了 负载、内存以及拒绝次数 等关键指标,每次查询返回线程池当前运行信息。

5. 线程池监控

hippo4j 提供了两种线程池运行时数据监控方式,分别是:

1、内置数据池数据采集 + 监控,无需依赖任何中间件,由 hippo4j 内部集成的方式运行。

2、使用三方中间件 Prometheus + Grafana 或 ElasticSearch + Grafana 采集和监控。

6. 整合 Spring ThreadPoolTaskExecutor

Spring ThreadPoolTaskExecutor 对原生线程池扩展了一部分功能,我认为比较实用有两个,并且 hippo4j 也已经支持。

  1. 当服务停止时,通知线程池处理剩余任务,并在等待指定时间后强制停止。

  2. 传递线程上下文到线程池执行上下文中。

第一个是实际使用中很核心的功能,减少了线程池丢弃任务的可能,这里重点说明下。

我们平时在停止应用时,有没有这样一个考虑,线程池中的任务真的都执行完成了吗?

可能执行完了,可能没有

Spring 基于以上考虑,注册了线程池销毁方法。在应用关闭时,如果发现线程池存在任务没有执行完,需要等待一个指定时间。指定时间内任务执行如果执行完毕,皆大欢喜;如果还存在没有结束的任务,则丢弃。

为什么会丢弃任务而不是再等等?

因为如果线程池任务长时间执行,会影响整个应用的停止,进行了折中处理。

7. 三方框架中间件线程池适配

hippo4j 的目标是兼容所有框架的线程池,并可以提供监控和动态修改的能力。

目前已支持的三方框架线程池列表:

  • Apache Dubbo

  • Alibaba Dubbo

  • RabbitMQ

  • Apache RocketMQ

  • SpringCloud Stream RocketMQ

  • SpringCloud Hystrix

  • Tomcat

  • Jetty

  • Undertow

支持上述框架线程池的动态变更参数和监控功能,比如:

未来 hippo4j 会支持更多三方框架线程池,如果你有好的想法也可以和我沟通。

8. 线程池运行堆栈查看

线程池运行中,任务运行停止,怀疑发生死锁或执行耗时操作。大多数程序员会选择使用命令或者 arthas 查看线程池运行中线程的堆栈,看看其中的 Worker 都在哪个方法卡住了。

hippo4j 基于以上痛点,推出了线程池运行堆栈实时查看功能。

9. 动态线程池对性能有无影响

这可能是很多开发者担心的一个点,在这里统一回复下。

hippo4j 仅对线程池做部分核心功能增强,没有修改任务执行源代码流程,可以保证绝对的安全。

其次,hippo4j 上述的功能,都是与线程池执行任务主流程外扩展的,不会影响线程池正常的执行性能。

hippo4j 支持的两种运行模式

hippo4j 为用户提供了两种运行模式,分别是轻量级的配置中心接入,和功能更齐全的服务端接入,下面都来说说各自的优缺点。

1. hippo4j config

依赖配置中心完成线程池的动态变更,已支持的配置中心有:Nacos、Apollo、Zookeeper、Etcd,未来还会接入 Consul 等。

另外,hippo4j 已支持用户自定义配置中心实现,如果使用公司自研或其它配置中心,也可以极小工作量进行引入。

使用 hippo4j config 模式的优点和不足:

  1. 优点:轻量级引入,可以根据项目中已有配置中心进行 hippo4j 的集成,无需引入其它服务,即可使用线程池参数动态化、运行时监控、报警等核心功能。

  2. 不足:缺少可视化控制台页面,上文中描述的诸多功能不能使用。

2. hippo4j server

需要部署 hippo4j Jar 包,涵盖上文中描述的所有功能。

因为服务端内部实现了配置中心和注册中心(参考 nacos 和 eureka 实现),所以它不依赖任何三方中间件。

  1. 优点:功能齐备,可以享受更多的服务和便利。如果应用启动的是集群,可以指定其中某一个实例的线程池修改,而 config 则是整个集群变更。

  2. 不足:相比较 hippo4j config,需要额外部署一个 jar 包,增加了部署工作量。

如果最初使用 hippo4j config,想要切换到 server,两者在进行替换的时候,无需修改业务代码

使用建议:根据公司情况选择,如果基本功能可以满足使用,选择 hippo4j config 使用即可;如果希望更多的功能,可以选择 hippo4j server。

项目发展近况

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/368550.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

数仓模型之维度建模

目录 1、数仓架构原则 2、如何搭建一个好的数仓 2.1 建模方法 2.2 建模解决的痛点 2.3 数仓系统满足的特性 2.4 数仓架构设计 3、维度建模 4、案例 5、问题讨论 今天我们来聊聊在数仓模型中举足轻重的维度建模。 简单而言,数据仓库的核心目标是为展现层提…

Hive学习——开窗函数精讲

目录 一、基于行的窗口函数——行的起点~行的终点 二、基于值的窗口函数——值的起点~值的终点 三、基于分区的窗口函数 四、基于缺省的窗口函数 五、lead与lag 六、first_value和last_value 七、排名函数——rank(113)、dense_rank(112)、row_number(123) 八、NTILE分…

nvm (node版本管理工具)安装的详细步骤,并解决安装过程中遇到的问题

1、下载NVM,跳转下载链接后,如下图,下载红框后解压文件 2、安装 注意:双击安装之后,会有两个地址选择, 1、地址中不能存在空格 2、不要放在C盘中,后面需要改个设置文件,安装到C盘的…

银行家算法

银行家算法 银行家算法是一种用来避免操作系统死锁出现的有效算法,所以在引入银行家算法的解释之前,有必要简单介绍一下死锁的概念。 一、死锁 死锁:是指两个或两个以上的进程在执行过程中,由于竞争资源或者由于彼此通信而造成…

Gitlab Linux 环境安装

环境检查是否已经安装了gitlab,安装了需要卸载# 检查当前环境是否已经安装了gitlab,并且查看版本 gitlab-rails console # 删除命令 yum remove git# 查找命令 rpm -qa | grep gitlab # 删除命令 rpm -e gitlab-ce-12.10.1-ce.0.el8.x86_64 # 查找命令f…

DS期末复习卷(八)

一、选择题(30分) 1.字符串的长度是指( C )。 (A) 串中不同字符的个数 (B) 串中不同字母的个数 (C ) 串中所含字符的个数 (D) 串中不同数字的个数 2.建立一个长度为n的有序单链表的时间复杂度为( C ) (A) O(n) (B) O(1) © …

小米/红米手机数据恢复:从小米手机恢复已删除的数据

如果您不小心删除了小米手机上的数据,后来发现您需要它,那么本文适合您。我将向您介绍一些最可靠的小米恢复方法,以将您的数据恢复到您的设备上。无论您是否有备份,都可以处理。让我们开始吧! 小米数据恢复 - 如何做&a…

一篇学习JVM

基础入门 1.JDK、JRE、JVM三者间的联系与区别 JDK JDK(Java SE Development Kit),Java标准开发包,它提供了编译、运行Java程序所需的各种工具和资源,包括Java编译器、Java运行时环境,以及常用的Java类库等。 下图是JDK的安装目…

博客管理系统--项目说明

项目体验地址(账号:123,密码:123)http://120.53.20.213:8080/blog_system/login.html项目码云Gitee地址:https://gitee.com/GoodManSS/project/tree/master/blog_system(一)准备工作…

【ArcGIS Pro二次开发】(7):地图(Map)的基本操作

地图是ArcGIS Pro中的基础起点,也是大多数工程的基础。主要用于显示表示空间数据的图层。 一、地图(Map)的基本操作示例 1、获取当前地图 var map MapView.Active.Map; 2、获取一级图层 var lys map.Layers; 用于获取地图中的单一图层,以及图层组…

【正点原子FPGA连载】第十六章DP彩条显示实验 摘自【正点原子】DFZU2EG_4EV MPSoC之嵌入式Vitis开发指南

1)实验平台:正点原子MPSoC开发板 2)平台购买地址:https://detail.tmall.com/item.htm?id692450874670 3)全套实验源码手册视频下载地址: http://www.openedv.com/thread-340252-1-1.html 第十六章DP彩条显…

什么是路由?

什么是路由? 介绍 **路由是指路由器从一个接口上收到数据包,根据数据包的目的地址进行定向并转发到另一个接口的过程。**路由发生在OSI网络参考模型中的第三层即网络层。 路由引导分组转送,经过一些中间的节点后,到它们最后的目…

六【 SpringMVC框架】

一 SpringMVC框架 目录一 SpringMVC框架1.什么是MVC2.SpringMVC概述3.SpringMVC常见开发方式4.SpringMVC执行流程5.SpringMVC核心组件介绍6.快速构建Spring MVC程序✅作者简介:Java-小白后端开发者 🥭公认外号:球场上的黑曼巴 🍎个…

工业三防平板可应用于各种复杂苛刻的工作环境

伴随着工业互联网技术的快速发展,生产制造自然环境繁杂,机器设备规定比较严苛。普通平板在工业场景户外场景等都比较容易出现磕碰或者出现其它因素如进水、进灰尘而引发设备故障。三防平板之所以在建筑工程的应用较为广泛,这与其独特的性能是…

线性数据结构:数组 Array

一、前言数组是数据结构还是数据类型?数组只是个名称,它可以描述一组操作,也可以命名这组操作。数组的数据操作,是通过 idx->val 的方式来处理。它不是具体要求内存上要存储着连续的数据才叫数组,而是说&#xff0c…

scratch和平使者 电子学会图形化编程scratch等级考试一级真题和答案解析2022年12月

目录 scratch和平使者 一、题目要求 1、准备工作 2、功能实现 二、案例分析

视图、游标、慢查询日志

Java知识点总结:想看的可以从这里进入 目录2.7、视图、游标2.7.1、视图2.7.2、游标2.7、慢查询日志2.7、视图、游标 2.7.1、视图 视图是一种虚拟存在的表,同真实表一样,视图也由列和行构成,它不存在于数据库中,是我们…

【红黑树】红黑树插入操作相关的细节和疑难拆解分析

本文就红黑树的插入操作进行细致到每一个小步骤的解析。1,成员变量本红黑树使用了三叉链结构,使用的时候尤其要记得处理指向父亲的指针。为何在节点的构造函数中,默认节点的颜色为红色?因为考虑到红黑树的性质(对于每个…

汇编语言 标志位总结

缩写原意: Overflow of = OV NV [No Overflow] Direction df = DN (decrement) UP (increment) Interrupt if = EI (enabled) DI (disabled) Sign sf = NG (negative) PL (positive) Zero zf = ZR [zero] NZ [ Not zero] Auxiliary Carry af = AC NA [ No AC ] Parity pf = PE…

计网个人作业05

R1 链路层可以提供如下服务 链路层服务IP能否提供?TCP能否提供?流量控制✔差错检测✔✔差错纠正全双工、半双工✔ R2 不冗余 IP层有丢包的情况⼀个⻓的 TCP 报⽂段会被分⽚成多个 IP 数据报形成不同的帧,不同的帧可能会被不同链路传输。同…