實(shí)戰(zhàn) | 生產(chǎn)環(huán)境中如何動(dòng)態(tài)調(diào)整線程池大???
環(huán)境:JDK17 + Nacos2.1.0
1. 簡(jiǎn)介
本文旨在探討如何結(jié)合Nacos作為動(dòng)態(tài)配置中心,實(shí)現(xiàn)在線動(dòng)態(tài)修改線程池大小的功能。將線程池大小的配置信息動(dòng)態(tài)地傳遞給應(yīng)用程序。此外,我們還將討論如何在應(yīng)用程序中監(jiān)聽配置變化,并根據(jù)新的配置信息動(dòng)態(tài)地調(diào)整線程池的大小。通過這種方式,我們可以提高系統(tǒng)的靈活性和可擴(kuò)展性,更好地適應(yīng)業(yè)務(wù)需求的變化。
2. 實(shí)戰(zhàn)案例
我們不會(huì)在SpringBoot項(xiàng)目中去使用,只是通過普通的maven項(xiàng)目進(jìn)行演示。
2.1 依賴管理
<properties>
<nacos.version>2.1.2</nacos.version>
<yaml.version>1.33</yaml.version>
<java.version>17</java.version>
</properties>
<dependency>
<groupId>com.alibaba.nacos</groupId>
<artifactId>nacos-client</artifactId>
<version>${nacos.version}</version>
<!-- 指定純凈版SDK -->
<classifier>pure</classifier>
</dependency>
<dependency>
<groupId>com.alibaba.nacos</groupId>
<artifactId>nacos-common</artifactId>
<version>${nacos.version}</version>
</dependency>
<dependency>
<groupId>com.alibaba.nacos</groupId>
<artifactId>nacos-api</artifactId>
<version>${nacos.version}</version>
</dependency>
<dependency>
<groupId>org.yaml</groupId>
<artifactId>snakeyaml</artifactId>
<version>${yaml.version}</version>
</dependency>
2.2 Nacos中初始配置
在Nacos中進(jìn)行線程池(核心數(shù),最大數(shù))初始配置
圖片
2.3 自定義Nacos監(jiān)聽器
編寫Nacos配置發(fā)生變化的監(jiān)聽器,該監(jiān)聽器的作用就是用來修改線程池的核心線程池?cái)?shù)及最大線程數(shù)。
public class NacosConfigListener {
public void start() throws Exception {
String serverAddr = "localhost:8848";
String dataId = "dy-thread.yaml";
String group = "dy";
Properties properties = new Properties();
properties.put("serverAddr", serverAddr);
properties.put("username", "nacos") ;
properties.put("password", "nacos") ;
ConfigService configService = NacosFactory.createConfigService(properties);
String content = configService.getConfig(dataId, group, 5000);
System.out.println("初始配置:\n" + content) ;
Yaml yaml = new Yaml() ;
configService.addListener(dataId, group, new Listener() {
public void receiveConfigInfo(String configInfo) {
try {
LinkedHashMap<String, Object> content = (LinkedHashMap<String, Object>) yaml.load(configInfo) ;
System.out.println("監(jiān)聽線程池修改:" + content) ;
// 當(dāng)內(nèi)容發(fā)生變化后,修改線程池的配置信息
LinkedHashMap<String, Object> dy = (LinkedHashMap<String, Object>) content.get("dy") ;
Integer coreSize = (Integer) dy.get("coreSize") ;
Integer maximumPoolSize = (Integer) dy.get("maximumPoolSize") ;
DynamicThreadPoolConfig.pool.setMaximumPoolSize(maximumPoolSize) ;
DynamicThreadPoolConfig.pool.setCorePoolSize(coreSize) ;
} catch (Exception e) {
e.printStackTrace() ;
}
}
@Override
public Executor getExecutor() {
return null ;
}
});
}
}
2.4 線程池使用
這里簡(jiǎn)單模擬使用線程池執(zhí)行任務(wù)。
public class DynamicThreadPoolConfig {
public static final ThreadPoolExecutor pool = new ThreadPoolExecutor(2, 3, 60, TimeUnit.SECONDS, new ArrayBlockingQueue<>(100)) ;
public static void main(String[] args) throws Exception {
// 啟動(dòng)監(jiān)聽器
new NacosConfigListener().start() ;
var schedule = new ScheduledThreadPoolExecutor(1) ;
// 以固定的周期打印線程池線程信息
schedule.scheduleAtFixedRate(() -> {
System.out.println(
"核心線程數(shù): " + pool.getCorePoolSize()
+ ", 最大線程數(shù): " + pool.getMaximumPoolSize()
+ ", 當(dāng)前活動(dòng)任務(wù)數(shù): " + pool.getActiveCount()
) ;
}, 0, 3, TimeUnit.SECONDS) ;
// 動(dòng)態(tài)添加任務(wù)
for (var i = 0; i < 100; i++) {
pool.execute(() -> {
try {
System.out.println(Thread.currentThread().getName()) ;
TimeUnit.SECONDS.sleep(10) ;
} catch (InterruptedException e) {
e.printStackTrace();
}
}) ;
}
}
}
2.5 測(cè)試
直接運(yùn)行程序,控制臺(tái)如下輸出
圖片
輸出的都是默認(rèn)值。接下來,通過nacos界面修改線程池大小
圖片
控制臺(tái)輸出
圖片
程序正確的監(jiān)聽到了配置發(fā)生了變化,同時(shí)修改了線程池的大小。
總結(jié):
在實(shí)際生產(chǎn)環(huán)境下,動(dòng)態(tài)修改線程池大小具有重要意義。以下是一些主要的原因:
- 適應(yīng)負(fù)載變化:應(yīng)用程序的負(fù)載可能會(huì)隨著時(shí)間、用戶數(shù)量、數(shù)據(jù)量等因素的變化而變化。如果線程池大小固定,那么在負(fù)載增加時(shí)可能會(huì)出現(xiàn)線程資源不足的情況,導(dǎo)致性能下降或響應(yīng)延遲。反之,如果負(fù)載降低,過多的線程可能會(huì)導(dǎo)致資源浪費(fèi)。因此,動(dòng)態(tài)調(diào)整線程池大小可以根據(jù)當(dāng)前的負(fù)載情況來優(yōu)化資源使用。
- 應(yīng)對(duì)突發(fā)流量:在某些情況下,應(yīng)用程序可能會(huì)突然接收到大量的請(qǐng)求,這被稱為突發(fā)流量。如果線程池大小固定且不足以處理這種突發(fā)流量,那么應(yīng)用程序的性能可能會(huì)受到嚴(yán)重影響。通過動(dòng)態(tài)調(diào)整線程池大小,可以快速地增加線程數(shù)量以應(yīng)對(duì)這種突發(fā)流量,從而保持應(yīng)用程序的穩(wěn)定性和性能。
- 提高系統(tǒng)靈活性:在生產(chǎn)環(huán)境中,應(yīng)用程序的需求和負(fù)載可能會(huì)隨著業(yè)務(wù)的發(fā)展而不斷變化。如果線程池大小固定,那么可能需要頻繁地重啟應(yīng)用程序或修改配置來適應(yīng)這些變化。而通過動(dòng)態(tài)調(diào)整線程池大小,可以在不重啟應(yīng)用程序的情況下,根據(jù)實(shí)際需求來靈活地調(diào)整線程資源,從而提高系統(tǒng)的靈活性。
總之,動(dòng)態(tài)修改線程池大小可以幫助應(yīng)用程序更好地適應(yīng)負(fù)載變化、應(yīng)對(duì)突發(fā)流量,并提高系統(tǒng)的靈活性和可擴(kuò)展性。這對(duì)于保持應(yīng)用程序的穩(wěn)定性和性能,以及滿足不斷變化的業(yè)務(wù)需求具有重要意義。