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