Dubbo框架線程池使用介紹
1、Dubbo已有線程池
dubbo在使用時,都是通過創(chuàng)建真實的業(yè)務線程池進行操作的。目前已知的線程池模型有兩個和java中的相互對應:
- fix: 表示創(chuàng)建固定大小的線程池。也是Dubbo默認的使用方式,默認創(chuàng)建的執(zhí)行線程數(shù)為200,并且是沒有任何等待隊列的。所以在極端的情況下可能會存在問題,比如某個操作大量執(zhí)行時,可能存在堵塞的情況。后面也會講相關的處理辦法。
- cache: 創(chuàng)建非固定大小的線程池,當線程不足時,會自動創(chuàng)建新的線程。但是使用這種的時候需要注意,如果突然有高TPS的請求過來,方法沒有及時完成,則會造成大量的線程創(chuàng)建,對系統(tǒng)的CPU和負載都是壓力,執(zhí)行越多反而會拖慢整個系統(tǒng)。
2、自定義線程池
在真實的使用過程中可能會因為使用fix模式的線程池,導致具體某些業(yè)務場景因為線程池中的線程數(shù)量不足而產(chǎn)生錯誤,而很多業(yè)務研發(fā)是對這些無感知的,只有當出現(xiàn)錯誤的時候才會去查看告警或者通過客戶反饋出現(xiàn)嚴重的問題才去查看,結果發(fā)現(xiàn)是線程池滿了。所以可以在創(chuàng)建線程池的時,通過某些手段對這個線程池進行監(jiān)控,這樣就可以進行及時的擴縮容機器或者告警。下面的這個程序就是這樣子的,會在創(chuàng)建線程池后進行對其監(jiān)控,并且及時作出相應處理。
(1)線程池實現(xiàn), 這里主要是基于對FixedThreadPool 中的實現(xiàn)做擴展出線程監(jiān)控的部分
package com.lagou.threadpool; import org.apache.dubbo.common.URL; import org.apache.dubbo.common.threadpool.support.fixed.FixedThreadPool; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.Map; import java.util.concurrent.*; public class WachingThreadPool extends FixedThreadPool implements Runnable { private static final Logger LOGGER = LoggerFactory.getLogger(WachingThreadPool.class); // 定義線程池使用的閥值 private static final double ALARM_PERCENT = 0.90; private final Map<URL, ThreadPoolExecutor> THREAD_POOLS = new ConcurrentHashMap<>(); public WachingThreadPool() { // 每隔3秒打印線程使用情況 Executors.newSingleThreadScheduledExecutor().scheduleWithFixedDelay(this, 1, 3, TimeUnit.SECONDS); } // 通過父類創(chuàng)建線程池 @Override public Executor getExecutor(URL url) { final Executor executor = super.getExecutor(url); if (executor instanceof ThreadPoolExecutor) { THREAD_POOLS.put(url, (ThreadPoolExecutor) executor); } return executor; } @Override public void run() { // 遍歷線程池 for (Map.Entry<URL, ThreadPoolExecutor> entry : THREAD_POOLS.entrySet()) { final URL url = entry.getKey(); final ThreadPoolExecutor executor = entry.getValue(); // 計算相關指標 final int activeCount = executor.getActiveCount(); final int poolSize = executor.getCorePoolSize(); double usedPercent = activeCount / (poolSize * 1.0); LOGGER.info("線程池執(zhí)行狀態(tài):[{}/{}:{}%]", activeCount, poolSize, usedPercent * 100); if (usedPercent > ALARM_PERCENT) { LOGGER.error("超出警戒線! host:{} 當前使用率是:{},URL:{}", url.getIp(), usedPercent * 100, url); } } } }
(2)SPI聲明,創(chuàng)建文件(固定的)
META-INF/dubbo/org.apache.dubbo.common.threadpool.ThreadPool
watching=包名.線程池名
(3)在服務提供方項目引入該依賴
(4)在服務提供方項目中設置使用該線程池生成器
dubbo.provider.threadpool=watching
(5)接下來需要做的就是模擬整個流程,因為該線程當前是每1秒抓一次數(shù)據(jù),所以我們需要對該方法的提供者超過1秒的時間(比如這里用休眠Thread.sleep ),消費者則需要啟動多個線程來并行執(zhí)行,來模擬整個并發(fā)情況。
(6)在調(diào)用方則嘗試簡單通過for循環(huán)啟動多個線程來執(zhí)行 查看服務提供方的監(jiān)控情況
package com.lagou; import com.lagou.bean.ConsumerComponent; import org.apache.dubbo.config.spring.context.annotation.EnableDubbo; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.PropertySource; import java.io.IOException; public class AnnotationConsumerMain { public static void main(String[] args) throws IOException, InterruptedException { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ConsumerConfiguration.class); context.start(); ConsumerComponent service = context.getBean(ConsumerComponent.class); while (true) { for (int i = 0; i < 1000; i++) { Thread.sleep(5); new Thread(new Runnable() { @Override public void run() { String msg = service.sayHello("world", 0); System.out.println(msg); } }).start(); } } } @Configuration @PropertySource("classpath:/dubbo-consumer.properties") //@EnableDubbo(scanBasePackages = "com.lagou.bean") @ComponentScan("com.lagou.bean") @EnableDubbo static class ConsumerConfiguration { } }
到此這篇關于Dubbo框架線程池使用介紹的文章就介紹到這了,更多相關Dubbo線程池內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
淺談Java中的final關鍵字與C#中的const, readonly關鍵字
下面小編就為大家?guī)硪黄獪\談Java中的final關鍵字與C#中的const, readonly關鍵字。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2016-10-10SpringBoot實現(xiàn)在webapp下直接訪問html,jsp
這篇文章主要介紹了SpringBoot實現(xiàn)在webapp下直接訪問html,jsp問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-10-10使用Java WebSocket獲取客戶端IP地址的示例代碼
在開發(fā)Web應用程序時,我們通常需要獲取客戶端的 IP 地址用于日志記錄、身份驗證、限制訪問等操作,本文將介紹如何使用Java WebSocket API獲取客戶端IP地址,以及如何在常見的WebSocket框架中獲得客戶端 IP地址,需要的朋友可以參考下2023-11-11request.getRequestURL()等方法得到路徑的區(qū)別及說明
這篇文章主要介紹了request.getRequestURL()等方法得到路徑的區(qū)別及說明,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2023-12-12Java實現(xiàn)兩人五子棋游戲(五) 判斷是否有一方勝出
這篇文章主要為大家詳細介紹了Java實現(xiàn)兩人五子棋游戲,判斷是否有一方勝出,具有一定的參考價值,感興趣的小伙伴們可以參考一下2018-03-03