当前位置: 首页 > news >正文

SpringBoot + Nacos 实现动态化线程池

1.背景

在后台开发中,会经常用到线程池技术,对于线程池核心参数的配置很大程度上依靠经验。然而,由于系统运行过程中存在的不确定性,我们很难一劳永逸地规划一个合理的线程池参数。

在对线程池配置参数进行调整时,一般需要对服务进行重启,这样修改的成本就会偏高。一种解决办法就是,将线程池的配置放到平台侧,运行开发同学根据系统运行情况对核心参数进行动态配置。

本文以Nacos作为服务配置中心,以修改线程池核心线程数、最大线程数为例,实现一个简单的动态化线程池。

2.code

1.依赖
<dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId><version>2021.1</version>
</dependency>
<dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId><version>2021.1</version>
</dependency>
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId>
</dependency>
2.配置yml文件

bootstrap.yml

server:port: 8090# 应用名称(nacos会将该名称当做服务名称)
spring:application:name: order-servicecloud:nacos:discovery:namespace: publicserver-addr: localhost:8848config:server-addr: localhost:8848file-extension: yml

application.yml

spring:profiles:active: dev

为什么要配置两个yml文件?

springboot中配置文件的加载是存在优先级顺序的,bootstrap优先级高于application。

nacos在项目初始化时,要保证先从配置中心进行配置拉取,拉取配置之后才能保证项目的正常启动。

3.nacos配置

登录到nacos管理页面,新建配置,如下图所示

注意Data ID的命名格式为,${spring.application.name}-${spring.profile.active}.${spring.cloud.nacos.config.file-extension} ,在本文中,Data ID的名字就是order-service-dev.yml

配置详情

这里我们只配置了两个参数,核心线程数量和最大线程数。

4.线程池配置和nacos配置变更监听
@RefreshScope
@Configuration
public class DynamicThreadPool implements InitializingBean {@Value("${core.size}")private String coreSize;@Value("${max.size}")private String maxSize;private static ThreadPoolExecutor threadPoolExecutor;@Autowiredprivate NacosConfigManager nacosConfigManager;@Autowiredprivate NacosConfigProperties nacosConfigProperties;@Overridepublic void afterPropertiesSet() throws Exception {//按照nacos配置初始化线程池threadPoolExecutor = new ThreadPoolExecutor(Integer.parseInt(coreSize), Integer.parseInt(maxSize), 10L, TimeUnit.SECONDS,new LinkedBlockingQueue<>(10),new ThreadFactoryBuilder().setNameFormat("c_t_%d").build(),new RejectedExecutionHandler() {@Overridepublic void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {System.out.println("rejected!");}});//nacos配置变更监听nacosConfigManager.getConfigService().addListener("order-service-dev.yml", nacosConfigProperties.getGroup(),new Listener() {@Overridepublic Executor getExecutor() {return null;}@Overridepublic void receiveConfigInfo(String configInfo) {//配置变更,修改线程池配置System.out.println(configInfo);changeThreadPoolConfig(Integer.parseInt(coreSize), Integer.parseInt(maxSize));}});}/*** 打印当前线程池的状态*/public String printThreadPoolStatus() {return String.format("core_size:%s,thread_current_size:%s;" +"thread_max_size:%s;queue_current_size:%s,total_task_count:%s", threadPoolExecutor.getCorePoolSize(),threadPoolExecutor.getActiveCount(), threadPoolExecutor.getMaximumPoolSize(), threadPoolExecutor.getQueue().size(),threadPoolExecutor.getTaskCount());}/*** 给线程池增加任务** @param count*/public void dynamicThreadPoolAddTask(int count) {for (int i = 0; i < count; i++) {int finalI = i;threadPoolExecutor.execute(new Runnable() {@Overridepublic void run() {try {System.out.println(finalI);Thread.sleep(10000);} catch (InterruptedException e) {e.printStackTrace();}}});}}/*** 修改线程池核心参数** @param coreSize* @param maxSize*/private void changeThreadPoolConfig(int coreSize, int maxSize) {threadPoolExecutor.setCorePoolSize(coreSize);threadPoolExecutor.setMaximumPoolSize(maxSize);}
}

这个代码就是实现动态线程池和核心了,需要说明的是:

  • @RefreshScope,这个注解用来支持nacos的动态刷新功能;

  • @Value("${max.size}")@Value("${core.size}"),这两个注解用来读取我们上一步在nacos配置的具体信息;同时,nacos配置变更时,能够实时读取到变更后的内容;

  • nacosConfigManager.getConfigService().addListener,配置监听,nacos配置变更时实时修改线程池的配置。

5.controller

为了观察线程池动态变更的效果,增加Controller类。

@RestController
@RequestMapping("/threadpool")
public class ThreadPoolController {@Autowiredprivate DynamicThreadPool dynamicThreadPool;/*** 打印当前线程池的状态*/@GetMapping("/print")public String printThreadPoolStatus() {return dynamicThreadPool.printThreadPoolStatus();}/*** 给线程池增加任务** @param count*/@GetMapping("/add")public String dynamicThreadPoolAddTask(int count) {dynamicThreadPool.dynamicThreadPoolAddTask(count);return String.valueOf(count);}
}
6.测试

启动项目,访问http://localhost:8090/threadpool/print打印当前线程池的配置。

可以看到,这个就是我们之前在nacos配置的线程数。

访问http://localhost:8090/threadpool/add?count=20增加20个任务。

重新打印线程池配置

可以看到已经有线程在排队了。

为了能够看到效果,我们多访问几次/add接口,增加任务数,在控制台出现拒绝信息时调整nacos配置。

此时,执行/add命令时,所有的线程都会提示rejected。

调整nacos配置,将核心线程数调整为50,最大线程数调整为100.

重新多次访问/add接口增加任务,发现没有拒绝信息了。这时,打印具体的线程状态,发现线程池参数修改成功。

相关文章:

SpringBoot + Nacos 实现动态化线程池

1.背景 在后台开发中&#xff0c;会经常用到线程池技术&#xff0c;对于线程池核心参数的配置很大程度上依靠经验。然而&#xff0c;由于系统运行过程中存在的不确定性&#xff0c;我们很难一劳永逸地规划一个合理的线程池参数。 在对线程池配置参数进行调整时&#xff0c;一…...

《Docker极简教程》--Dockerfile--Dockerfile的基本语法

Dockerfile是一种文本文件&#xff0c;用于定义Docker镜像的内容和构建步骤。它包含一系列指令&#xff0c;每个指令代表一个构建步骤&#xff0c;从基础镜像开始&#xff0c;逐步构建出最终的镜像。通过Dockerfile&#xff0c;用户可以精确地描述应用程序运行环境的配置、依赖…...

css中, grid-auto-rows: 怎样简写在grid:中

grid-auto-rows:100px; grid-template-columns:1fr 1fr; &#x1f446;可以写成&#x1f447; grid:auto-flow 100px / 1fr 1fr;在CSS Grid布局中&#xff0c;grid-auto-rows 属性用于指定自动生成的网格容器的行的大小。如果你想要将 grid-auto-rows 的值简写在 grid 属性中&a…...

@ 代码随想录算法训练营第8周(C语言)|Day53(动态规划)

代码随想录算法训练营第8周&#xff08;C语言&#xff09;|Day53&#xff08;动态规划&#xff09; Day50、动态规划&#xff08;包含题目 ● 123.买卖股票的最佳时机III ● 188.买卖股票的最佳时机IV &#xff09; 123.买卖股票的最佳时机III 题目描述 给定一个数组 price…...

算法-矩阵置零

1、题目来源 73. 矩阵置零 - 力扣&#xff08;LeetCode&#xff09; 2、题目描述 给定一个 m x n 的矩阵&#xff0c;如果一个元素为 0 &#xff0c;则将其所在行和列的所有元素都设为 0 。请使用 原地 算法。 示例 1&#xff1a; 输入&#xff1a;matrix [[1,1,1],[1,0,1…...

xilinx除法器的使用

平台&#xff1a;Vivado2018.3. 芯片&#xff1a;xcku115-flva1517-2-i (active) 最近学习使用了xilinx除法器&#xff0c;在使用过程中出现了很多次除法器的结果和我预计的结果不一致&#xff0c;特此记录学习一下。 参考文件&#xff1a;pg151.下载地址 pg151-div-gen.pdf …...

算法沉淀——递归(leetcode真题剖析)

算法沉淀——递归 01.汉诺塔问题02.合并两个有序链表03.反转链表04.两两交换链表中的节点05.Pow(x, n) 递归是一种通过调用自身的方式来解决问题的算法。在递归算法中&#xff0c;问题被分解为更小的相似子问题&#xff0c;然后通过对这些子问题的解进行组合来解决原始问题。递…...

BERT模型中的input_ids和attention_mask参数

一、概述 1.1 input_ids 在BERT模型及其衍生体中&#xff0c;输入文本首先经过一个分词处理流程&#xff0c;其中文本被细分为单词或子单词&#xff08;subwords&#xff09;&#xff0c;每个分词随后映射到一个唯一的整数标识符。这些标识符组成了所谓的input_ids数组&#x…...

java+vue_springboot企业设备安全信息系统14jbc

企业防爆安全信息系统采用B/S架构&#xff0c;数据库是MySQL。网站的搭建与开发采用了先进的java进行编写&#xff0c;使用了vue框架。该系统从三个对象&#xff1a;由管理员、人员和企业来对系统进行设计构建。主要功能包括&#xff1a;个人信息修改&#xff0c;对人员管理&am…...

vulhub中Apache Log4j Server 反序列化命令执行漏洞复现(CVE-2017-5645)

Apache Log4j是一个用于Java的日志记录库&#xff0c;其支持启动远程日志服务器。Apache Log4j 2.8.2之前的2.x版本中存在安全漏洞。攻击者可利用该漏洞执行任意代码。 1.我们使用ysoserial生成payload&#xff0c;然后直接发送给your-ip:4712端口即可。 java -jar ysoserial-…...

基于python+django+vue.js开发的医院门诊管理系统/医疗管理系统

功能介绍 平台采用B/S结构&#xff0c;后端采用主流的Python语言进行开发&#xff0c;前端采用主流的Vue.js进行开发。 功能包括&#xff1a;医生管理、科室管理、护士管理、住院管理、药品管理、用户管理、日志管理、系统信息模块。 源码地址 https://github.com/geeeeeee…...

Linux文件系统笔记

文章目录 FILE SYSTEM软硬链接 动静态库 使用别人提供的库 FILE SYSTEM 文件的管理工作&#xff1a; 1.基础知识&#xff1a; 文件 属性 内容不是所有文件都会打开所有的打开的&#xff0c;未打开的文件会进行管理未打开文件&#xff0c;要能做到快速定位文件磁盘–物理存…...

vue封装el-table表格组件

先上效果图&#xff1a; 本文包含了具名插槽、作用域插槽、jsx语法三种&#xff1a; Render.vue&#xff08;很重要&#xff0c;必须有&#xff09;: <script> export default {name: "FreeRender",functional: true,props: {scope:Object,render: Functio…...

「Python系列」Python数据结构

文章目录 一、数据结构二、相关链接 一、数据结构 Python提供了多种内置的数据结构&#xff0c;这些数据结构在编程中非常有用。以下是Python中常见的一些数据结构&#xff1a; 列表&#xff08;List&#xff09;: 列表是Python中最常用的数据结构之一&#xff0c;它是一个有…...

MySQL多实例部署:从概念到实操的全面指南

目录 MySQL多实例管理 单实例 什么是多实例 多实例的好处 多实例的弊端 MySQL多实例用在哪些场景 资金紧张的公司 用户并发访问量不大的业务 大型网站也有用多实例 部署MySQL多实例 rpm和源码的优缺点 二进制方式安装mysql 准备二进制mysql运行所需的环境 准备多…...

C++学习Day07之虚函数和纯虚函数

目录 前言一、程序及输出1.1 虚函数1.2 纯虚函数1.2.1 定义、示例1.2.2 引入原因1.2.3 抽象类 二、分析与总结 前言 在 C 中&#xff0c;虚函数和纯虚函数是实现多态性的重要概念。虚函数是在基类中声明为虚函数的函数&#xff0c;在派生类中可以被重写&#xff0c;实现动态联…...

GZ036 区块链技术应用赛项赛题第9套

2023年全国职业院校技能大赛 高职组 “区块链技术应用” 赛项赛卷&#xff08;9卷&#xff09; 任 务 书 参赛队编号&#xff1a; 背景描述 随着异地务工人员的增多&#xff0c;房屋租赁成为一个广阔是市场&#xff1b;目前&#xff0c;现有技术中的房屋租赁是由…...

微服务—RabbitMQ高级(延迟消息)

本博客为个人学习笔记&#xff0c;学习网站&#xff1a;2023黑马程序员RabbitMQ入门到实战教程 高级篇章节 目录 延迟消息 死信交换机 延迟消息插件 下载安装 延迟交换机声明 ​编辑 发送延迟消息 订单状态同步问题 延迟消息 在电商的支付业务中&#xff0c;对于一些库…...

香港服务器如何取消windows的自动更新

大家用过电脑的人对windows系统的自动更新应该都不会陌生&#xff0c;其实香港服务器的使用也是一样的方法。为什么要对香港服 务器windows的自动更新进行关闭呢&#xff1f;其主要原因在于&#xff0c;有些更新是不能更新&#xff0c;一更新话&#xff0c;系统反而会变得不稳定…...

kali虚拟机桥接模式快速设置

第一步&#xff1a;选择 虚拟机 > 设置 > 虚拟机设置&#xff0c;设置桥接模式 不选择复制物理网络连接状态选项&#xff1a; 如果采用DHCP的方式来分配IP地址&#xff0c;当电脑网络从有线或无线网络之间进行移动时&#xff0c;DHCP会重新分配ip地址&#xff0c;即虚拟机…...

在软件开发中正确使用MySQL日期时间类型的深度解析

在日常软件开发场景中&#xff0c;时间信息的存储是底层且核心的需求。从金融交易的精确记账时间、用户操作的行为日志&#xff0c;到供应链系统的物流节点时间戳&#xff0c;时间数据的准确性直接决定业务逻辑的可靠性。MySQL作为主流关系型数据库&#xff0c;其日期时间类型的…...

内存分配函数malloc kmalloc vmalloc

内存分配函数malloc kmalloc vmalloc malloc实现步骤: 1)请求大小调整:首先,malloc 需要调整用户请求的大小,以适应内部数据结构(例如,可能需要存储额外的元数据)。通常,这包括对齐调整,确保分配的内存地址满足特定硬件要求(如对齐到8字节或16字节边界)。 2)空闲…...

Linux链表操作全解析

Linux C语言链表深度解析与实战技巧 一、链表基础概念与内核链表优势1.1 为什么使用链表&#xff1f;1.2 Linux 内核链表与用户态链表的区别 二、内核链表结构与宏解析常用宏/函数 三、内核链表的优点四、用户态链表示例五、双向循环链表在内核中的实现优势5.1 插入效率5.2 安全…...

利用ngx_stream_return_module构建简易 TCP/UDP 响应网关

一、模块概述 ngx_stream_return_module 提供了一个极简的指令&#xff1a; return <value>;在收到客户端连接后&#xff0c;立即将 <value> 写回并关闭连接。<value> 支持内嵌文本和内置变量&#xff08;如 $time_iso8601、$remote_addr 等&#xff09;&a…...

基于Flask实现的医疗保险欺诈识别监测模型

基于Flask实现的医疗保险欺诈识别监测模型 项目截图 项目简介 社会医疗保险是国家通过立法形式强制实施&#xff0c;由雇主和个人按一定比例缴纳保险费&#xff0c;建立社会医疗保险基金&#xff0c;支付雇员医疗费用的一种医疗保险制度&#xff0c; 它是促进社会文明和进步的…...

【磁盘】每天掌握一个Linux命令 - iostat

目录 【磁盘】每天掌握一个Linux命令 - iostat工具概述安装方式核心功能基础用法进阶操作实战案例面试题场景生产场景 注意事项 【磁盘】每天掌握一个Linux命令 - iostat 工具概述 iostat&#xff08;I/O Statistics&#xff09;是Linux系统下用于监视系统输入输出设备和CPU使…...

leetcodeSQL解题:3564. 季节性销售分析

leetcodeSQL解题&#xff1a;3564. 季节性销售分析 题目&#xff1a; 表&#xff1a;sales ---------------------- | Column Name | Type | ---------------------- | sale_id | int | | product_id | int | | sale_date | date | | quantity | int | | price | decimal | -…...

JVM暂停(Stop-The-World,STW)的原因分类及对应排查方案

JVM暂停(Stop-The-World,STW)的完整原因分类及对应排查方案,结合JVM运行机制和常见故障场景整理而成: 一、GC相关暂停​​ 1. ​​安全点(Safepoint)阻塞​​ ​​现象​​:JVM暂停但无GC日志,日志显示No GCs detected。​​原因​​:JVM等待所有线程进入安全点(如…...

RNN避坑指南:从数学推导到LSTM/GRU工业级部署实战流程

本文较长&#xff0c;建议点赞收藏&#xff0c;以免遗失。更多AI大模型应用开发学习视频及资料&#xff0c;尽在聚客AI学院。 本文全面剖析RNN核心原理&#xff0c;深入讲解梯度消失/爆炸问题&#xff0c;并通过LSTM/GRU结构实现解决方案&#xff0c;提供时间序列预测和文本生成…...

AirSim/Cosys-AirSim 游戏开发(四)外部固定位置监控相机

这个博客介绍了如何通过 settings.json 文件添加一个无人机外的 固定位置监控相机&#xff0c;因为在使用过程中发现 Airsim 对外部监控相机的描述模糊&#xff0c;而 Cosys-Airsim 在官方文档中没有提供外部监控相机设置&#xff0c;最后在源码示例中找到了&#xff0c;所以感…...