Spring Cloud Alibaba - 利用Nacos实现高效动态线程池管理

文章目录

  • 引言
  • 概述
  • 什么是动态线程池
  • Nacos简介
  • 如何利用Nacos实现动态线程池管理
  • 应用场景
  • Code
    • 版本说明
    • POM
    • 配置文件
      • Nacos Config配置文件加载顺序
        • 1. bootstrap.yml的加载
        • 2. application.yml的加载
        • 注意事项
        • 示例
    • nacos配置
      • Data Id
      • Nacos中Data ID的命名格式解释
        • `${spring.application.name}`
        • `${spring.profile.active}`
        • `${spring.cloud.nacos.config.file-extension}`
        • 合并后的Data ID
        • 示例
    • Configuration & Change Callback
  • 测试
  • 小结

在这里插入图片描述


引言

Java线程池实现原理及其在美团业务中的实践

开源组件:Hippo4J 、 dynamic-tp


概述

随着现代应用程序的复杂性不断增加,动态线程池管理成为了构建可靠和高效系统的关键之一。而Nacos作为一个优秀的服务发现和配置中心,能够帮助我们实现动态线程池的灵活管理。

我们这里将介绍如何利用Nacos来实现高效的动态线程池管理,并探讨其在分布式系统中的应用。

什么是动态线程池

在软件开发中,线程池是一种管理和重用线程的机制,它能够有效地控制并发执行的线程数量,避免资源耗尽和性能下降。动态线程池则是在传统线程池的基础上,能够根据系统负载和资源需求动态调整线程数量的一种改进型线程池管理方式。


Nacos简介

Nacos是阿里巴巴开源的一款多功能的服务发现和配置中心,它提供了服务注册与发现、动态配置管理、服务路由等功能,被广泛应用于微服务架构中。其优势在于高可用、易扩展、支持多种注册中心和配置源等特性。


如何利用Nacos实现动态线程池管理

  1. 服务注册与发现:首先,将应用程序注册到Nacos服务注册中心,使其成为Nacos的服务实例。这样,我们就可以利用Nacos的服务发现功能来获取可用的服务实例列表。

  2. 动态配置管理:借助Nacos的动态配置管理功能,我们可以将线程池的配置信息存储在Nacos的配置中心中,例如线程池大小、核心线程数、最大线程数、线程存活时间等参数。

  3. 监听配置变更:通过监听Nacos配置中心的变更通知,当线程池配置发生改变时,我们可以及时感知并动态调整线程池的参数,从而实现线程池的动态管理。

  4. 实时监控与调整:结合Nacos的服务监控和告警功能,可以实现对线程池运行状态的实时监控,当发现异常或负载过高时,及时进行调整,保障系统的稳定性和性能。


应用场景

利用Nacos实现动态线程池管理适用于各种需要动态调整线程数量的场景,特别适用于:

  • 微服务架构下的服务调用和资源管理;
  • Web服务器、消息队列等高并发场景的应用;
  • 云计算环境下的资源弹性伸缩。

Code

在这里插入图片描述

版本说明

:: Spring Boot ::                             (v2.4.1)
spring-cloud-starter-alibaba-nacos-discovery   2021.1
spring-cloud-starter-alibaba-nacos-config      2021.1

POM

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><artifactId>boot2</artifactId><groupId>com.artisan</groupId><version>0.0.1-SNAPSHOT</version></parent><groupId>com.artisan</groupId><artifactId>boot-threadpool-nacos</artifactId><version>0.0.1-SNAPSHOT</version><name>boot-threadpool-nacos</name><description>boot-threadpool-nacos</description><properties><java.version>8</java.version></properties><dependencies><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><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.projectlombok</groupId><artifactId>lombok</artifactId></dependency><!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-bootstrap --><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-bootstrap</artifactId><version>3.1.8</version></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build></project>

配置文件

bootstrap.yml

server:port: 9090# 应用名称(会注册到Nacos上)
spring:application:name: artisan-servicecloud:nacos:discovery:namespace: publicserver-addr: 127.0.0.1:8848config:server-addr: 127.0.0.1:8848file-extension: yml

application.yml

spring:profiles:active: dev

Nacos Config配置文件加载顺序

在使用Spring Boot结合Nacos作为配置中心时,配置文件的加载顺序是非常重要的。一般来说,Spring Boot应用会先加载bootstrap.yml(或bootstrap.properties),再加载application.yml(或application.properties)。下面我们来详细解释这个加载顺序。

1. bootstrap.yml的加载

当Spring Boot应用启动时,首先会加载bootstrap.yml(或bootstrap.properties)文件。这个文件通常用于一些系统级别的配置,例如日志系统的配置、应用的环境变量配置等。在使用Nacos作为配置中心时,可以在bootstrap.yml中配置Nacos的相关参数,如Nacos的服务地址、命名空间等。

2. application.yml的加载

接着,Spring Boot会加载application.yml(或application.properties)文件。这个文件包含了应用程序的业务逻辑相关的配置,如数据库连接信息、端口配置、服务注册信息等。

注意事项
  • 加载顺序优先级: 在Spring Boot中,bootstrap.yml的加载优先级高于application.yml。这意味着如果在bootstrap.yml中配置了某些参数,而在application.yml中也有相同的配置项,那么以bootstrap.yml中的配置为准。
  • Nacos配置优先级: 如果将Nacos作为配置中心,那么Nacos中的配置会覆盖本地配置文件(如bootstrap.yml、application.yml)中的配置。因此,建议将系统级别的配置放在bootstrap.yml中,并将业务逻辑相关的配置放在Nacos中,以便实现配置的分离管理和动态更新。
示例

下面是一个简单的示例,展示了bootstrap.yml和application.yml的配置内容:

# bootstrap.yml
spring:application:name: my-applicationcloud:nacos:config:server-addr: localhost:8848namespace: your-namespace
# application.yml
server:port: 8080

在这个示例中,bootstrap.yml中配置了Nacos的服务地址和命名空间,而application.yml中配置了应用程序的端口号。


nacos配置

在这里插入图片描述

在这里插入图片描述
我们目前只配置了两个参数,核心线程数量和最大线程数。

Data Id

Nacos中Data ID的命名格式解释

在Nacos中,Data ID是用来唯一标识配置信息的,而其命名格式一般遵循一定的规则,以便于系统的管理和查找。

${spring.application.name}-${spring.profile.active}.${spring.cloud.nacos.config.file-extension}就是一种常见的Data ID命名格式

${spring.application.name}

${spring.application.name}表示Spring Boot应用的名称,它是在application.propertiesapplication.yml中通过spring.application.name属性进行配置的。这个属性通常用来标识应用的名称,用于服务注册、日志输出等场景。

${spring.profile.active}

${spring.profile.active}表示Spring Boot应用当前的Profile,它是通过spring.profiles.active属性进行配置的。Profile用于区分不同环境下的配置信息,例如devtestprod等,可以根据实际情况进行配置。

${spring.cloud.nacos.config.file-extension}

${spring.cloud.nacos.config.file-extension}表示配置文件的扩展名,它是通过spring.cloud.nacos.config.file-extension属性进行配置的。在Nacos中,配置信息可以是properties格式或yaml格式的文件,通过指定扩展名来区分不同类型的配置文件,如.properties.yaml

合并后的Data ID

将上述三部分内容按照规定的格式进行合并,就得到了Nacos中Data ID的命名格式:${spring.application.name}-${spring.profile.active}.${spring.cloud.nacos.config.file-extension}。这个命名格式能够唯一标识一个配置文件,并且包含了应用名称、Profile和配置文件类型等信息,方便系统根据需要进行查找和加载。

示例

假设我们有一个名为my-application的Spring Boot应用,当前处于dev环境,并且使用properties格式的配置文件,那么对应的Data ID就是:my-application-dev.properties

那我们这里的就是 artisan-service-dev.yml

在这里插入图片描述


Configuration & Change Callback

package com.artisan.bootthreadpoolnacos.config;import com.alibaba.cloud.nacos.NacosConfigManager;
import com.alibaba.cloud.nacos.NacosConfigProperties;
import com.alibaba.nacos.api.config.listener.Listener;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.context.annotation.Configuration;import java.util.concurrent.*;/*** @author 小工匠* @version 1.0* @mark: show me the code , change the world*/
@RefreshScope
@Configuration
@Slf4j
public class DynamicThreadPoolConfig 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) {log.info("Warn Warn Warn : rejected executed!!!");}});//nacos配置变更监听nacosConfigManager.getConfigService().addListener("order-service-dev.yml", nacosConfigProperties.getGroup(),new Listener() {@Overridepublic Executor getExecutor() {return null;}@Overridepublic void receiveConfigInfo(String configInfo) {//配置变更,修改线程池配置log.info("收到Nacos Config Server推来的配置变更,修改线程池配置", 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(() -> {try {log.info("dynamicThreadPoolAddTask->", 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);}
}

动态线程池的配置类,主要功能包括根据Nacos配置动态调整线程池的核心参数,并监听Nacos配置的变化。

  • @RefreshScope是Spring Cloud中的一个注解,用于实现配置信息的热更新。当使用Nacos作为配置中心时,结合@RefreshScope注解可以实现配置信息的动态刷新,即在配置信息发生变化时,应用程序可以动态地重新加载最新的配置信息,而不需要重启应用。 在上述代码中,@RefreshScope注解被用于配置类DynamicThreadPoolConfig上。这意味着当Nacos中的配置信息发生变化时,Spring容器会自动检测到变化,并重新创建被@RefreshScope注解修饰的Bean,以便应用程序能够获取到最新的配置信息。 通过结合@RefreshScope注解和Nacos配置中心,可以实现应用程序在运行时动态地响应配置变化,从而实现更加灵活和可维护的系统配置管理。
  • core.sizemax.size是从Nacos中获取的配置参数,分别代表线程池的核心线程数和最大线程数。
  • afterPropertiesSet方法是InitializingBean接口的实现方法,在Bean属性设置后被调用。在这个方法中,初始化了线程池,并注册了Nacos配置的监听器。
  • printThreadPoolStatus方法用于打印当前线程池的状态信息。
  • dynamicThreadPoolAddTask方法用于向线程池中添加任务。
  • changeThreadPoolConfig方法用于修改线程池的核心参数,例如核心线程数和最大线程数。

测试

package com.artisan.bootthreadpoolnacos.controller;import com.artisan.bootthreadpoolnacos.config.DynamicThreadPoolConfig;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;/*** @author 小工匠* @version 1.0* @mark: show me the code , change the world*/@RestController
@RequestMapping("/dtp")
public class ThreadPoolController {@Autowiredprivate DynamicThreadPoolConfig dynamicThreadPool;/*** 打印当前线程池的状态*/@GetMapping("/info")public String printThreadPoolStatus() {return dynamicThreadPool.printThreadPoolStatus();}/*** 给线程池增加任务** @param count*/@GetMapping("/add")public String dynamicThreadPoolAddTask(int count) {dynamicThreadPool.dynamicThreadPoolAddTask(count);return String.valueOf(count);}
}
  • 启动Nacos server
  • 启动应用

在这里插入图片描述

打印基本信息

在这里插入图片描述

增加任务,观察执行情况

http://localhost:9090/dtp/add?count=100

日志输出

在这里插入图片描述

Nacos上修改配置信息

在这里插入图片描述

观察日志和信息

在这里插入图片描述

在这里插入图片描述


小结

通过本文的介绍,我们了解了如何利用Nacos实现高效的动态线程池管理,以及其在分布式系统中的应用场景。动态线程池的灵活调整能够有效地提升系统的性能和稳定性,而Nacos作为一个优秀的服务发现和配置中心,为我们提供了强大的支持和便利,帮助我们更好地构建可靠和高效的分布式应用系统。

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【漏洞复现】大华智慧园区综合管理平台信息泄露漏洞

Nx01 产品简介 大华智慧园区综合管理平台是一款综合管理平台&#xff0c;具备园区运营、资源调配和智能服务等功能。该平台旨在协助优化园区资源分配&#xff0c;满足多元化的管理需求&#xff0c;同时通过提供智能服务&#xff0c;增强使用体验。 Nx02 漏洞描述 大华智慧园区…

测试老鸟总结,自动化测试框架从0到1,一篇打通...

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 1、自动化测试框架…

STL常用容器(string容器)---C++

STL常用容器目录 1.string容器1.1 string基本概念1.2 string构造函数1.3 string赋值操作1.4 string字符串拼接1.5 string查找和替换1.6 string字符串比较1.7 string字符存取1.8 string插入和删除1.9 string子串 1.string容器 1.1 string基本概念 本质&#xff1a; string是C…

AI:135-基于卷积神经网络的艺术品瑕疵检测与修复

🚀点击这里跳转到本专栏,可查阅专栏顶置最新的指南宝典~ 🎉🎊🎉 你的技术旅程将在这里启航! 从基础到实践,深入学习。无论你是初学者还是经验丰富的老手,对于本专栏案例和项目实践都有参考学习意义。 ✨✨✨ 每一个案例都附带关键代码,详细讲解供大家学习,希望…

C/C++暴力/枚举/穷举题目持续更新(刷蓝桥杯基础题的进!)

目录 前言 一、百钱买百鸡 二、百元兑钞 三、门牌号码&#xff08;蓝桥杯真题&#xff09; 四、相乘&#xff08;蓝桥杯真题&#xff09; 五、卡片拼数字&#xff08;蓝桥杯真题&#xff09; 六、货物摆放&#xff08;蓝桥杯真题&#xff09; 七、最短路径&#xff08;蓝…

基于 java springboot+layui仓库管理系统

基于 java springbootlayui仓库管理系统设计和实现 博主介绍&#xff1a;5年java开发经验&#xff0c;专注Java开发、定制、远程、文档编写指导等,csdn特邀作者、专注于Java技术领域 作者主页 央顺技术团队 Java毕设项目精品实战案例《1000套》 欢迎点赞 收藏 ⭐留言 文末获取源…

MySQL - 事务日志

目录 1. redo日志 1.1 为什么需要REDO日志 1.2 REDO日志的好处、特点 1. 好处 2. 特点 1.3 redo的组成 1.4 redo的整体流程 1.5 redo log的刷盘策略 1.6 不同刷盘策略演示 1. 流程图 ​编辑2. 举例 1.7 写入redo log buffer 过程 1.8 redo log file 1. 相关参数…

如何学习VBA_3.2.16-17:VBA中的判断函数及数组的基本概念

我给VBA的定义&#xff1a;VBA是个人小型自动化处理的有效工具。利用好了&#xff0c;可以大大提高自己的劳动效率&#xff0c;而且可以提高数据处理的准确度。我推出的VBA系列教程共九套和一部VBA汉英手册&#xff0c;现在已经全部完成&#xff0c;希望大家利用、学习。 如果…

内核解读之内存管理(8)什么是page cache

文章目录 0. 文件系统的层次结构1.什么是page cache2.感观认识page cache3. Page Cache的优缺点3.1 Page Cache 的优势3.2 Page Cache 的劣势 0. 文件系统的层次结构 在了解page cache之前&#xff0c;我们先看下文件系统的层次结构。 1 VFS 层 VFS &#xff08; Virtual Fi…

Vue | (五)使用Vue脚手架(中)| 尚硅谷Vue2.0+Vue3.0全套教程

文章目录 &#x1f4da;Todo-list 案例&#x1f407;组件化编码流程&#xff08;通用&#xff09;&#x1f407;实现静态组件&#x1f407;展示动态数据&#x1f407;交互⭐️添加一个todo⭐️todo勾选实现⭐️删除功能实现⭐️底部统计功能实现⭐️底部全选功能实现⭐️底部一…

Linux---进程间通信(下)

1、System V 共享内存 原理如下图 系统调用接口介绍 int shmget(key_t key, size_t size, int shmflg) 功能&#xff1a;用来创建共享内存 参数 key&#xff1a;这个共享内存段名字&#xff0c;内核用key来标识共享内存size&#xff1a;共享内存大小shmflg&#xff1a;由九个权…

软件游戏显示d3dx9_42.dll丢失的5种解决方法,快速解决dll问题

当计算机系统中d3dx9_42.dll文件丢失时&#xff0c;可能会引发一系列运行问题和功能异常&#xff0c;具体表现形式多样且影响范围较广。首先&#xff0c;对于依赖于DirectX 9.0c版本的各类应用程序&#xff0c;尤其是部分经典的老款游戏&#xff0c;由于d3dx9_42.dll是其中不可…