Spring?Cloud?Gateway中netty線程池優(yōu)化示例詳解
一、背景描述
最近測試同學(xué)對系統(tǒng)進(jìn)行壓測。報出一個問題:幾乎所有接口的成績都不太好。甚至一些僅僅是主鍵查詢,并且數(shù)據(jù)量不大的接口也是如此。排查過程中:跳過gateway網(wǎng)關(guān),直接通過目標(biāo)服務(wù)器ip進(jìn)行壓測發(fā)現(xiàn)成績提升明顯。初步判斷是網(wǎng)關(guān)問題。網(wǎng)上翻閱資料發(fā)現(xiàn)一個優(yōu)化點,就是netty本身的線程池配置。
二、線程池配置
要設(shè)置可同時工作的線程數(shù)需要設(shè)置netty中的reactor.netty.ioWorkerCount
參數(shù)。該參數(shù)無法直接配置,需要通過System.setProperty
設(shè)置,故我們可以創(chuàng)建以下配置類來配置該參數(shù):
@Configuration public static class ReactNettyConfiguration { @Bean public ReactorResourceFactory reactorClientResourceFactory() { System.setProperty("reactor.netty.ioSelectCount","1"); // 這里工作線程數(shù)為2-4倍都可以。看具體情況 int ioWorkerCount = Math.max(Runtime.getRuntime().availableProcessors()*3, 4)); System.setProperty("reactor.netty.ioWorkerCount",String.valueOf(ioWorkerCount); return new ReactorResourceFactory(); } }
我這里版本是reactor-netty-core-1.0.3
,版本不一樣的話 可能參數(shù)key不太一樣??梢钥匆幌翷oopResources 中寫的key。
Runtime.getRuntime().availableProcessors()
獲取的是cpu核心線程數(shù)也就是計算資源,而不是CPU物理核心數(shù),對于支持超線程的CPU來說,單個物理處理器相當(dāng)于擁有兩個邏輯處理器,能夠同時執(zhí)行兩個線程。
三、源碼分析
package reactor.netty.resources; import io.netty.channel.Channel; import io.netty.channel.EventLoopGroup; import java.time.Duration; import java.util.Objects; import reactor.core.Disposable; import reactor.core.publisher.Mono; @FunctionalInterface public interface LoopResources extends Disposable { // 這里是worker線程數(shù),未配置的話。從cpu核心數(shù)和4直接取一個大的 int DEFAULT_IO_WORKER_COUNT = Integer.parseInt(System.getProperty("reactor.netty.ioWorkerCount", "" + Math.max(Runtime.getRuntime().availableProcessors(), 4))); // 這里是select線程數(shù) 默認(rèn)是-1 int DEFAULT_IO_SELECT_COUNT = Integer.parseInt(System.getProperty("reactor.netty.ioSelectCount", "-1")); .... // 創(chuàng)建一個默認(rèn)的資源,把兩個線程數(shù)的參數(shù)傳遞過去 static LoopResources create(String prefix) { if (Objects.requireNonNull(prefix, "prefix").isEmpty()) { throw new IllegalArgumentException("Cannot use empty prefix"); } return new DefaultLoopResources(prefix, DEFAULT_IO_SELECT_COUNT, DEFAULT_IO_WORKER_COUNT, true); } ....
接下來看一下 DefaultLoopResources做了什么
DefaultLoopResources(String prefix, int selectCount, int workerCount, boolean daemon) { this.running = new AtomicBoolean(true); this.daemon = daemon; this.workerCount = workerCount; this.prefix = prefix; this.serverLoops = new AtomicReference<>(); this.clientLoops = new AtomicReference<>(); this.cacheNativeClientLoops = new AtomicReference<>(); this.cacheNativeServerLoops = new AtomicReference<>(); // 因為默認(rèn)沒有配置 所以selectCode必然是-1 if (selectCount == -1) { this.selectCount = workerCount; // serverSelectLoops沒有創(chuàng)建,而是直接使用的serverLoops this.serverSelectLoops = this.serverLoops; this.cacheNativeSelectLoops = this.cacheNativeServerLoops; } else { this.selectCount = selectCount; this.serverSelectLoops = new AtomicReference<>(); this.cacheNativeSelectLoops = new AtomicReference<>(); } } @SuppressWarnings("FutureReturnValueIgnored") EventLoopGroup cacheNioSelectLoops() { // 兩個相等的話 使用 cacheNioServerLoops 返回工作組 if (serverSelectLoops == serverLoops) { return cacheNioServerLoops(); } EventLoopGroup eventLoopGroup = serverSelectLoops.get(); if (null == eventLoopGroup) { EventLoopGroup newEventLoopGroup = new NioEventLoopGroup(selectCount, threadFactory(this, "select-nio")); if (!serverSelectLoops.compareAndSet(null, newEventLoopGroup)) { //"FutureReturnValueIgnored" this is deliberate newEventLoopGroup.shutdownGracefully(0, 0, TimeUnit.MILLISECONDS); } eventLoopGroup = cacheNioSelectLoops(); } return eventLoopGroup; } // 這里相當(dāng)于返回了工作組 @SuppressWarnings("FutureReturnValueIgnored") EventLoopGroup cacheNioServerLoops() { EventLoopGroup eventLoopGroup = serverLoops.get(); if (null == eventLoopGroup) { EventLoopGroup newEventLoopGroup = new NioEventLoopGroup(workerCount, threadFactory(this, "nio")); if (!serverLoops.compareAndSet(null, newEventLoopGroup)) { //"FutureReturnValueIgnored" this is deliberate newEventLoopGroup.shutdownGracefully(0, 0, TimeUnit.MILLISECONDS); } eventLoopGroup = cacheNioServerLoops(); } return eventLoopGroup; }
可以看出來,如果未配置。netty是沒有select線程組的。結(jié)合分析reactor模型可以發(fā)現(xiàn),這種情況對處理效率是有影響的。而且最大只和cpu核心數(shù)量相同的配置也明顯無法重復(fù)利硬件用資源。
參考:http://www.dbjr.com.cn/program/292774r05.htm
以上就是Spring Cloud Gateway中netty線程池優(yōu)化的詳細(xì)內(nèi)容,更多關(guān)于Spring Cloud Gateway中netty線程池優(yōu)化的資料請關(guān)注腳本之家其它相關(guān)文章!
- SpringCloud-Gateway轉(zhuǎn)發(fā)WebSocket失敗問題及解決
- spring?cloud?gateway中配置uri三種方式
- spring?cloud?gateway中netty線程池小優(yōu)化
- SpringCloudGateway使用Skywalking時日志打印traceId解析
- SpringCloud?Gateway之請求應(yīng)答日志打印方式
- Spring Cloud gateway 網(wǎng)關(guān)如何攔截Post請求日志
- Spring Cloud Gateway 記錄請求應(yīng)答數(shù)據(jù)日志操作
- 基于Spring-cloud-gateway實現(xiàn)全局日志記錄的方法
相關(guān)文章
Java實現(xiàn)指定線程執(zhí)行順序的三種方式示例
這篇文章主要介紹了Java實現(xiàn)指定線程執(zhí)行順序的三種方式,包括通過共享對象鎖加上可見變量,通過主線程Join()以及通過線程執(zhí)行時Join()等三種實現(xiàn)方法,需要的朋友可以參考下2019-01-01Spring Cloud Gateway(讀取、修改 Request Body)的操作
這篇文章主要介紹了Spring Cloud Gateway(讀取、修改 Request Body)的操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-12-12SpringBoot使用validation做參數(shù)校驗說明
這篇文章主要介紹了SpringBoot使用validation做參數(shù)校驗說明,首先通過添加hibernate-validator展開全文內(nèi)容,具有一定的參考價值,需要的小伙伴可以參考與喜愛2022-04-04Spring中的@Autowired、@Qualifier和@Primary注解詳解
這篇文章主要介紹了Spring中的@Autowired、@Qualifier和@Primary注解詳解,@Autowired?注解,可以對類成員變量、方法和構(gòu)造函數(shù)進(jìn)行標(biāo)注,完成自動裝配的工作,@Autowired?是默認(rèn)根據(jù)?byType?進(jìn)行自動裝配的,需要的朋友可以參考下2023-11-11Java調(diào)用opencv實現(xiàn)圖片矯正功能
這篇文章主要為大家詳細(xì)介紹了Java如何調(diào)用opencv實現(xiàn)圖片矯正功能,文中的示例代碼簡潔易懂,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2023-09-09