线程池是一种基于 池化思想管理线程 的工具,使用线程池可以减少 创建销毁线程的开销,避免线程过多导致 系统资源耗尽。在 高并发以及大批量 的任务处理场景,线程池的使用是必不可少的。
如果有在项目中实际使用线程池,相信你可能会遇到以下痛点:
基于以上诸多痛点,小马哥着手 hippo4j 的开发,致力于打造标准线程池 动态变更 和 监控 的中间件框架。
Gitee:https://gitee.com/agentart/hippo4j
hippo4j 通过对 JDK ThreadPoolExecutor 线程池增强,以及扩展三方框架底层线程池等功能,为业务系统提高线上运行保障能力。
小贴士:hippo4j 不止于 Java ThreadPoolExecutor 的增强,Dubbo
、RabbitMQ
、RocketMQ
、Hystrix
、Tomcat
、Jetty
、Undertow
等框架线程池也都有进行监控和动态变更。
在系统开发的过程中,因为涉及到多人协作,难免会出现信息不互通的情况。在同一个系统,对于线程池来说,常见的是线程池随意定义。
user-log-record-thread-pool
;member-log-record-thread-pool
;power-log-record-thread-pool
;随着系统不断开发,相同或不同语义的线程池被定义的越来越多,间接导致服务器资源严重耗损。
而如果系统中使用 hippo4j,能够在控制台查看当前应用已有线程池,是否存在相同语义且业务可复用线程池实例,避免线程资源过度浪费。
业务中使用了线程池,十个程序员可能有九个都在犯嘀咕,这线程池的配置应该如何选择?
我觉得犯纠结的点主要有两个,无外乎设置的数多了或者少了。
大家都知道,如果要修改运行中应用线程池参数,需要停止线上应用,调整成功后再发布,而这个过程异常的繁琐,如果能在运行中动态调整线程池的参数多好。
美团技术团队基于这些痛点,推出了动态线程池的概念,催生了一批动态线程池框架,hippo4j 也是其一。
如果应用是集群部署,hippo4j 可以选择修改线程池 某一实例,或者修改 集群全部实例,运行时生效,不需要再重启服务。
再比如,压测时使用 hippo4j 动态调整线程池参数,对于开发测试来说,也是个不错的选择。
从线程池运行时监控的角度出发,hippo4j 内置 4 种报警策略,线程池活跃度、阻塞队列容量、拒绝策略触发以及任务运行超时报警。
hippo4j 支持钉钉、企业微信和飞书软件通知,线程池任务运行超时报警示例:
线程池在服务运行过程中,对开发者来说是一个完全的黑盒。开发者无法得知线程池的参数变化,比如阻塞队列数量或者完成任务数等核心参数,这对于排查问题来说并不友好。
hippo4j 支持线程池运行时状态实时查看,并在核心参数的基础上扩展了 负载、内存以及拒绝次数 等关键指标,每次查询返回线程池当前运行信息。
hippo4j 提供了两种线程池运行时数据监控方式,分别是:
1、内置数据池数据采集 + 监控,无需依赖任何中间件,由 hippo4j 内部集成的方式运行。
2、使用三方中间件 Prometheus + Grafana 或 ElasticSearch + Grafana 采集和监控。
Spring ThreadPoolTaskExecutor
对原生线程池扩展了一部分功能,我认为比较实用有两个,并且 hippo4j 也已经支持。
第一个是实际使用中很核心的功能,减少了线程池丢弃任务的可能,这里重点说明下。
我们平时在停止应用时,有没有这样一个考虑,线程池中的任务真的都执行完成了吗?
可能执行完了,可能没有。
Spring 基于以上考虑,注册了线程池销毁方法。在应用关闭时,如果发现线程池存在任务没有执行完,需要等待一个指定时间。指定时间内任务执行如果执行完毕,皆大欢喜;如果还存在没有结束的任务,则丢弃。
为什么会丢弃任务而不是再等等?
因为如果线程池任务长时间执行,会影响整个应用的停止,进行了折中处理。
hippo4j 的目标是兼容所有框架的线程池,并可以提供监控和动态修改的能力。
目前已支持的三方框架线程池列表:
支持上述框架线程池的动态变更参数和监控功能,比如:
未来 hippo4j 会支持更多三方框架线程池,如果你有好的想法也可以和我沟通。
线程池运行中,任务运行停止,怀疑发生死锁或执行耗时操作。大多数程序员会选择使用命令或者 arthas 查看线程池运行中线程的堆栈,看看其中的 Worker 都在哪个方法卡住了。
hippo4j 基于以上痛点,推出了线程池运行堆栈实时查看功能。
这可能是很多开发者担心的一个点,在这里统一回复下。
hippo4j 仅对线程池做部分核心功能增强,没有修改任务执行源代码流程,可以保证绝对的安全。
其次,hippo4j 上述的功能,都是与线程池执行任务主流程外扩展的,不会影响线程池正常的执行性能。
hippo4j 为用户提供了两种运行模式,分别是轻量级的配置中心接入,和功能更齐全的服务端接入,下面都来说说各自的优缺点。
依赖配置中心完成线程池的动态变更,已支持的配置中心有:Nacos、Apollo、Zookeeper,未来还会接入 Etcd、Consul 等。
另外,hippo4j 已支持用户自定义配置中心实现,如果使用公司自研或其它配置中心,也可以极小工作量进行引入。
使用 hippo4j config 模式的优点和不足:
需要部署 hippo4j Jar 包,涵盖上文中描述的所有功能。
因为服务端内部实现了配置中心和注册中心(参考 nacos 和 eureka 实现),所以它不依赖任何三方中间件。
如果最初使用 hippo4j config,想要切换到 server,两者在进行替换的时候,无需修改业务代码。
使用建议:根据公司情况选择,如果基本功能可以满足使用,选择 hippo4j config 使用即可;如果希望更多的功能,可以选择 hippo4j server。
如果各位看官觉得有用,麻烦各位大佬在 Gitee star 支持下,非常感谢。
2022 年 11 月 06 日,Hippo4j 1.4.3 版本正式发布! Hippo4j 是一个线程池框架,基于 JDK 原生线程池扩展了诸多功能,比如:运行时动态变更线程池参数、采集线程池运行时数据以及多种维度线程池报警等,为业务系统提高线上运行保障能力。 项目自 2021 年 6 月份开源,一直保持快速迭代,共经历 17 次版本发布,已知 23 家公司登记使用。截止目前,共计 83 位开源
登录报错 : javax.net.ssl.SSLHandshakeException: No appropriate protocol (protocol is disabled or cipher suites are inappropriate) 是因为数据库不支持ssl,需要关闭ssl 数据库链接上加上&useSSL=false
问题内容: 我有一个运行时间很长的过程,可以监听事件并进行一些激烈的处理。 目前,我通常用于限制并发运行的作业数量,但是根据一天中的时间以及其他各种因素,我希望能够动态地增加或减少并发线程的数量。 如果我减少了并发线程的数量,那么我希望当前正在运行的作业能够很好地完成。 是否有Java库可以让我控制并动态增加或减少线程池中运行的并发线程数?(该类必须实现ExecutorService)。 我必须自
最近,我一直在尝试寻找一个用于线程并发任务的库。理想情况下,一个简单的接口,调用线程上的函数。任何时候都有n个线程,有些线程完成得比其他线程快,并且在不同的时间到达。 首先我在试Rx,这在c语言中很好。我也研究了区块和TBB,但它们都依赖于平台。对于我的原型,我需要保持平台独立性,因为我们还不知道它将在什么平台上运行,并且在做出决定时可以更改。 C 11有很多关于线程和并发的东西,我发现了很多关于
我的应用程序中有如下工作流:可以有X个用户请求(通常同时有5-10个),他们希望在系统中搜索某些东西(每个请求在单独的线程中处理)。 每个搜索都可以并行处理(我目前正在实现)。线程/CPU使用实际上不是这里的问题,因为这些任务不需要占用CPU。数据库是瓶颈。 目前,我只为搜索机制设置了一个单独的DB连接池-最大池大小设置为10。我知道这不多,但我不能把它设置得更高。现在我试图弄清楚如何为每个搜索(
本文向大家介绍Java 线程池框架,包括了Java 线程池框架的使用技巧和注意事项,需要的朋友参考一下 一、线程池结构图 二、示例 定义线程接口 1:newSingleThreadExecutor 输入结果: 2:newFixedThreadPool 输入结果: 3 :newCachedThreadPool 输入结果: 4 :ScheduledThreadPoolExecutor 输入结果: 三、
我正在写一个小的多线程超文本传输协议文件下载程序,并希望能够缩小可用的线程,因为代码遇到错误 这些错误将特定于在web服务器不允许任何更多连接的情况下返回的http错误 eg.如果我设置了一个由5个线程组成的池,每个线程都试图打开自己的连接并下载文件块。服务器可能只允许2个连接,我相信会返回503个错误,我想检测到这一点并关闭一个线程,最终限制池的大小,大概只有服务器允许的2个 我能让线自动停止吗
我试图理解可观察性是如何工作的,我想展示当前线程以更好地理解。整个应用程序是用java 8构建的,并使用lambda表达式。没有太多的经验,我发现用这样的表达式显示当前线程有一些困难: 我喜欢这样写: 但是我找不到一种方法来做它作为订阅(Schedulers.io())和观察(Schedulers.computation())返回和单一,没有办法把这样的东西: 谢谢