SpringCloud組件性能優(yōu)化的技巧
Springcloud 的性能問題
Springcloud 原始的配置,性能是很低的,大家可以使用 Jmeter 測試一下,QPS 不會到 50。
要做到高并發(fā),需要做不少的配置優(yōu)化,主要的配置優(yōu)化有以下幾點:
- Feign 配置優(yōu)化
- hystrix 配置 優(yōu)化
- ribbon 優(yōu)化
- Servlet 容器 優(yōu)化
- Zuul 配置 優(yōu)化
應(yīng)用服務(wù)組件調(diào)優(yōu)
Servlet 容器 優(yōu)化
默認情況下,Spring Boot 使用 Tomcat 來作為內(nèi)嵌的 Servlet 容器,可以將 Web 服務(wù)器切換到 Undertow 來提高應(yīng)用性能,Undertow 是紅帽公司開發(fā)的一款基于 NIO 的高性能 Web 嵌入式
Zuul 使用的內(nèi)置容器默認是 Tomcat,可以將其換成 undertow,可以顯著減少線程的數(shù)量,替換方式即在 pom 中添加以下內(nèi)容:
第一步,移除 Tomcat 依賴
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <exclusions> <exclusion> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-tomcat</artifactId> </exclusion> </exclusions> </dependency>
第二步,增加 Untertow 依賴
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-undertow</artifactId> </dependency>
第三步, Undertow 的屬性配置
server: undertow: io-threads: 16 worker-threads: 256 buffer-size: 1024 buffers-per-region: 1024 direct-buffers: true
server.undertow.io-threads: 設(shè)置 IO 線程數(shù), 它主要執(zhí)行非阻塞的任務(wù), 它們會負責(zé)多個連接, 默認設(shè)置每個 CPU 核心一個線程, 不要設(shè)置過大,如果過大,啟動項目會報錯:打開文件數(shù)過多
server.undertow.worker-threads: 阻塞任務(wù)線程池, 當(dāng)執(zhí)行類似 servlet 請求阻塞 IO 操作, undertow 會從這個線程池中取得線程, 它的值設(shè)置取決于系統(tǒng)線程執(zhí)行任務(wù)的阻塞系數(shù),默認值是 IO 線程數(shù) * 8
server.undertow.buffer-size: 以下的配置會影響 buffer, 這些 buffer 會用于服務(wù)器連接的 IO 操作, 有點類似 netty 的池化內(nèi)存管理, 每塊 buffer 的空間大小, 越小的空間被利用越充分,不要設(shè)置太大,以免影響其他應(yīng)用,合適即可
server.undertow.buffers-per-region: 每個區(qū)分配的 buffer 數(shù)量 , 所以 pool 的大小是 buffer-size * buffers-per-region
server.undertow.direct-buffers: 是否分配的直接內(nèi)存 (NIO 直接分配的堆外內(nèi)存)
Feign 配置優(yōu)化
feign 默認不啟用 hystrix,需要手動指定 feign.hystrix.enabled=true 開啟熔斷
feign 啟用壓縮也是一種有效的性能優(yōu)化方式,具體的配置如下
feign: compression: request: enabled: true mime-types: text/xml,application/xml,application/json response: enabled: true
feign HTTP 請求方式選擇 feign 默認使用的是基于 JDK 提供的 URLConnection 調(diào)用 HTTP 接口,不具備連接池, 所以資源開銷上有點影響,經(jīng)測試 JDK 的 URLConnection 比 Apache HttpClient 快很多倍。Apache HttpClient 和 okhttp 都支持配置連接池功能, 也可以使用 okhttp 請求方式。 當(dāng)使用 HttpClient 時,可如下設(shè)置:
feign: httpclient: enabled: true max-connections:1000 max-connections-per-route: 200
當(dāng)使用 OKHttp 時,可如下設(shè)置:
feign: okhttp: enabled: true httpclient: max-connections: 1000 max-connections-per-route: 200
max-connections 設(shè)置整個連接池最大連接數(shù)(該值默認為 200), 根據(jù)自己的場景決定 max-connections-per-route 設(shè)置路由的默認最大連接(該值默認為 50),限制數(shù)量實際使用
Gateway 組件調(diào)優(yōu)
Zuul 配置 優(yōu)化
我們知道 Hystrix 有隔離策略:THREAD 以及 SEMAPHORE ,默認是 SEMAPHORE 。
Zuul 默認是使用信號量隔離,并且信號量的大小是 100,請求的并發(fā)線程超過 100 就會報錯,可以調(diào)大該信號量的最大值來提高性能,配置如下:
zuul: semaphore: max-semaphores: 5000
表示,當(dāng) Zuul 的隔離策略為 SEMAPHORE 時,設(shè)置指定服務(wù)的最大信號量為 5000。對于特定的微服務(wù),可以通過下面的方式,設(shè)置最大信號量
設(shè)置默認最大信號量:
zuul:
semaphore:
max-semaphores: 5000 # 默認值
設(shè)置指定服務(wù)的最大信號量:
zuul: semaphore: max-semaphores: 5000
為了方便 ThreadLocal 的使用,也可以改為使用線程隔離的策略,這種場景下,就需要調(diào)大 hystrix 線程池線程大小,該線程池默認 10 個線程,調(diào)整的配置示例如下:
zuul: ribbonIsolationStrategy: THREAD hystrix: threadpool: default: coreSize: 100 maximumSize: 400 allowMaximumSizeToDivergeFromCoreSize: true maxQueueSize: -1
hystrix.threadpool.default.allowMaximumSizeToDivergeFromCoreSize:是否讓 maximumSize 生效,false 的話則只有 coreSize 會生效
hystrix.threadpool.default.maxQueueSize:線程池的隊列大小,-1 代表使用 SynchronousQueue 隊列
hystrix.threadpool.default.maximumSize:最大線程數(shù)量
hystrix.threadpool.default.allowMaximumSizeToDivergeFromCoreSize:是否讓 maximumSize 生效,false 的話則只有 coreSize 會生效
hystrix.threadpool.default.maxQueueSize:線程池的隊列大小,-1 代表使用 SynchronousQueue 隊列
zuul.ribbon-isolation-strategy: 設(shè)置線程隔離,thread 線程隔離,SEMAPHORE 表示信號量隔離
默認配置都可以去 HystrixThreadPoolProperties 和 ZuulProperties 這兩個 java 文件中查找
hystrix 配置 優(yōu)化
首先需要設(shè)置參數(shù) hystrix.threadpool.default.coreSize 來指定熔斷隔離的線程數(shù),這個數(shù)需要調(diào)優(yōu),經(jīng)測試線程數(shù)我們設(shè)置為和提供方的容器線程差不多,吞吐量高許多。
其次,啟用 Hystrix 后,很多服務(wù)當(dāng)?shù)谝淮卧L問的時候都會失敗 是因為初始化負載均衡一系列操作已經(jīng)超出了超時時間了,因為默認的超時時間為 1S,需要修改超時時間參數(shù),方可解決這個問題。
參考的 hystrix 配置如下:
hystrix: threadpool: default: coreSize: 500 command: default: circuitBreaker: requestVolumeThreshold: 1000 fallback: enabled: true execution: isolation: thread: timeoutInMilliseconds: 100000
hystrix.command.default: 全局的作用域,作用的所有的 hystrix 的客戶端, 如果需要對某個微服務(wù),可以寫 serviceId
hystrix.command.default.fallback.enabled 是否開啟回退方法
hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds 請求處理的超時時間,缺省為 1000, 表示默認的超時時間為 1S
hystrix.threadpool.default.coreSize 核心線程池數(shù)量
hystrix.command.default.fallback.isolation.semaphore.maxConcurrentRequests 回退最大線程數(shù)
hystrix.command.default.circuitBreaker.requestVolumeThreshold 熔斷器失敗的個數(shù),進入熔斷器的請求達到 1000 時服務(wù)降級(之后的請求直接進入熔斷器)
ribbon 優(yōu)化
Ribbon 進行客戶端負載均衡的 Client 并不是在服務(wù)啟動的時候就初始化好的,而是在調(diào)用的時候才會去創(chuàng)建相應(yīng)的 Client,所以第一次調(diào)用的耗時不僅僅包含發(fā)送 HTTP 請求的時間,還包含了創(chuàng)建 RibbonClient 的時間,這樣一來如果創(chuàng)建時間速度較慢,同時設(shè)置的超時時間又比較短的話,很容易就會出現(xiàn)上面所描述的顯現(xiàn)。
因此我們可以通過設(shè)置:
ribbon: eager-load: enabled:true clients:service-1,service-2,service-n
參數(shù)說明:
ribbon.eager-load.enabled : 開啟 Ribbon 的饑餓加載模式
ribbon.eager-load.clients: 指定需要饑餓加載的服務(wù)名,如果不指定服務(wù)名稱,饑餓加載模式無效
Zuul 的饑餓加載,沒有設(shè)計專門的參數(shù)來配置,而是直接采用了讀取路由配置來進行饑餓加載。所以,如果我們使用默認路由,而沒有通過配置的方式指定具體路由規(guī)則,那么 zuul.ribbon.eager-load.enabled=true 的配置就沒有什么作用了。
如果需要真正啟用 Zuul 的饑餓加載,需要通過 zuul.ignored-services=* 來忽略所有的默認路由,讓所有路由配置均維護在配置文件中,以達到網(wǎng)關(guān)啟動的時候就加載好各個路由的負載均衡對象。
關(guān)于 Zuul 的默認路由,這里詳細介紹一下。假設(shè)你的注冊服務(wù)中心有三個已經(jīng)注冊的服務(wù)名稱 service-a,service-b,service-c。但是在 zuul 配置文件中,只映射了 service-a,service-b,如下:
zuul: ribbon: eager-load: enabled: true ignored-services: ‘*' routes: a: path: /a/** serviceId: service-a b: path: /b/** serviceId: service-b
這里,雖然沒有配置 service-c 的映射,但是,由于 zuul 有默認的映射機制,還是可以通過 //ip:port/service-c / 的 Url,訪問到你的 service-c 服務(wù),如果不想向外界暴露默認的服務(wù)映射,可以加上 zuul.ignored-services:*
到此這篇關(guān)于SpringCloud組件性能優(yōu)化的技巧的文章就介紹到這了,更多相關(guān)SpringCloud組件優(yōu)化內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Springboot如何配置yml文件與映射到j(luò)ava類
這篇文章主要介紹了Springboot如何配置yml文件與映射到j(luò)ava類問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2023-09-09Springcloud-nacos實現(xiàn)配置和注冊中心的方法
這篇文章主要介紹了Springcloud-nacos實現(xiàn)配置和注冊中心的方法,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-07-07SpringBoot項目中使用Netty實現(xiàn)遠程調(diào)用的示例代碼
眾所周知在進行網(wǎng)絡(luò)連接的時候,建立套接字連接是一個非常消耗性能的事情,特別是在分布式的情況下,那么該通過什么技術(shù)去解決上述的問題呢,本文小編給大家介紹了SpringBoot項目中使用Netty實現(xiàn)遠程調(diào)用的方法,需要的朋友可以參考下2025-04-04使用IDEA如何打包發(fā)布SpringBoot并部署到云服務(wù)器
這篇文章主要介紹了使用IDEA如何打包發(fā)布SpringBoot并部署到云服務(wù)器問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2023-12-12