瘋狂創客圈 Java 高併發【 億級流量聊天室實戰】實戰系列之15 【博客園總入口 】html
瘋狂創客圈(筆者尼恩建立的高併發研習社羣)Springcloud 高併發系列文章,將爲你們介紹三個版本的 高併發秒殺:java
1、版本1 :springcloud + zookeeper 秒殺web
2、版本2 :springcloud + redis 分佈式鎖秒殺面試
3、版本3 :springcloud + Nginx + Lua 高性能版本秒殺redis
以及有關Springcloud 幾篇核心、重要的文章:spring
1、Springcloud 配置, 史上最全 一文全懂sql
2、Springcloud 中 SpringBoot 配置全集 , 收藏版json
3、Feign Ribbon Hystrix 三者關係 , 史上最全 深度解析tomcat
4、SpringCloud gateway 詳解 , 史上最全性能優化
這是《Springcloud 高併發 配置 | 一文全懂》篇,爲你們解讀若是作到Springcloud 高併發 配置。
Springcloud 原始的配置,性能是很低的,你們可使用Jmeter測試一下,QPS不會到50。要作到高併發,須要作很多的配置優化,主要的配置優化有如下幾點:
默認狀況下,Spring Boot 使用 Tomcat 來做爲內嵌的 Servlet 容器,能夠將 Web 服務器切換到 Undertow 來提升應用性能,Undertow 是紅帽公司開發的一款基於 NIO 的高性能 Web 嵌入式
Zuul使用的內置容器默認是Tomcat,能夠將其換成undertow,能夠顯著減小線程的數量,替換方式即在pom中添加如下內容:
第一步,移除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: 設置IO線程數, 它主要執行非阻塞的任務,它們會負責多個鏈接, 默認設置每一個CPU核心一個線程,不要設置過大,若是過大,啓動項目會報錯:打開文件數過多
server.undertow.worker-threads: 阻塞任務線程池, 當執行相似servlet請求阻塞IO操做, undertow會從這個線程池中取得線程,它的值設置取決於系統線程執行任務的阻塞係數,默認值是IO線程數8
server.undertow.buffer-size: 如下的配置會影響buffer,這些buffer會用於服務器鏈接的IO操做,有點相似netty的池化內存管理,每塊buffer的空間大小,越小的空間被利用越充分,不要設置太大,以避免影響其餘應用,合適便可
server.undertow.buffers-per-region: 每一個區分配的buffer數量 , 因此pool的大小是buffer-size buffers-per-region
server.undertow.direct-buffers: 是否分配的直接內存(NIO直接分配的堆外內存)
咱們知道Hystrix有隔離策略:THREAD 以及SEMAPHORE ,默認是 SEMAPHORE 。
Zuul默認是使用信號量隔離,而且信號量的大小是100,請求的併發線程超過100就會報錯,能夠調大該信號量的最大值來提升性能,配置以下:
zuul: semaphore: max-semaphores: 5000
表示,當Zuul的隔離策略爲SEMAPHORE時,設置指定服務的最大信號量爲5000。對於特定的微服務,能夠經過下面的方式,設置最大信號量
設置默認最大信號量:
zuul:
semaphore:
max-semaphores: 5000 # 默認值
設置指定服務的最大信號量:
zuul: eureka: <commandKey>: semaphore: max-semaphores: 5000
爲了方便ThreadLocal的使用,也能夠改成使用線程隔離的策略,這種場景下,就須要調大hystrix線程池線程大小,該線程池默認10個線程,調整的配置示例以下:
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:最大線程數量
hystrix.threadpool.default.allowMaximumSizeToDivergeFromCoreSize:是否讓maximumSize生效,false的話則只有coreSize會生效
hystrix.threadpool.default.maxQueueSize:線程池的隊列大小,-1表明使用SynchronousQueue隊列
zuul.ribbon-isolation-strategy:設置線程隔離,thread 線程隔離,SEMAPHORE 表示信號量隔離
默認配置均可以去HystrixThreadPoolProperties和ZuulProperties這兩個java文件中查找
feign 默認不啓用hystrix,須要手動指定 feign.hystrix.enabled=true 開啓熔斷
feign 啓用壓縮也是一種有效的性能優化方式,具體的配置以下
feign: compression: request: enabled: true mime-types: text/xml,application/xml,application/json response: enabled: true
feign HTTP請求方式選擇
feign默認使用的是基於JDK提供的URLConnection調用HTTP接口,不具有鏈接池,因此資源開銷上有點影響,經測試JDK的URLConnection比Apache HttpClient快不少倍。Apache HttpClient和okhttp都支持配置鏈接池功能,也可使用okhttp請求方式。
當使用HttpClient時,可以下設置:
feign: httpclient: enabled: true max-connections:1000 max-connections-per-route: 200
當使用OKHttp時,可以下設置:
feign: okhttp: enabled: true httpclient: max-connections: 1000 max-connections-per-route: 200
max-connections 設置整個鏈接池最大鏈接數(該值默認爲200), 根據本身的場景決定
max-connections-per-route 設置路由的默認最大鏈接(該值默認爲50),限制數量實際使用
首先須要設置參數hystrix.threadpool.default.coreSize 來指定熔斷隔離的線程數,這個數須要調優,經測試線程數咱們設置爲和提供方的容器線程差很少,吞吐量高許多。
其次,啓用Hystrix後,不少服務當第一次訪問的時候都會失敗 是由於初始化負載均衡一系列操做已經超出了超時時間了,由於默認的超時時間爲1S,須要修改超時時間參數,方可解決這個問題。
參考的hystrix配置以下:
hystrix: threadpool: default: coreSize: 500 command: default: circuitBreaker: requestVolumeThreshold: 1000 fallback: enabled: true execution: isolation: thread: timeoutInMilliseconds: 100000
hystrix.command.default: 全局的做用域,做用的全部的hystrix的客戶端,若是須要對某個微服務,能夠寫serviceId
hystrix.command.default.fallback.enabled 是否開啓回退方法
hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds 請求處理的超時時間,缺省爲1000,表示默認的超時時間爲1S
hystrix.threadpool.default.coreSize 核心線程池數量
hystrix.command.default.fallback.isolation.semaphore.maxConcurrentRequests 回退最大線程數
hystrix.command.default.circuitBreaker.requestVolumeThreshold 熔斷器失敗的個數,進入熔斷器的請求達到1000時服務降級(以後的請求直接進入熔斷器)
Ribbon進行客戶端負載均衡的Client並非在服務啓動的時候就初始化好的,而是在調用的時候纔會去建立相應的Client,因此第一次調用的耗時不只僅包含發送HTTP請求的時間,還包含了建立RibbonClient的時間,這樣一來若是建立時間速度較慢,同時設置的超時時間又比較短的話,很容易就會出現上面所描述的顯現。
所以咱們能夠經過設置:
ribbon: eager-load: enabled:true clients:service-1,service-2,service-n
參數說明:
ribbon.eager-load.enabled : 開啓Ribbon的飢餓加載模式
ribbon.eager-load.clients: 指定須要飢餓加載的服務名,若是不指定服務名稱,飢餓加載模式無效
Zuul的飢餓加載,沒有設計專門的參數來配置,而是直接採用了讀取路由配置來進行飢餓加載。因此,若是咱們使用默認路由,而沒有經過配置的方式指定具體路由規則,那麼 zuul.ribbon.eager-load.enabled=true 的配置就沒有什麼做用了。
若是須要真正啓用Zuul 的飢餓加載,須要經過zuul.ignored-services=*
來忽略全部的默認路由,讓全部路由配置均維護在配置文件中,以達到網關啓動的時候就加載好各個路由的負載均衡對象。
關於Zuul 的默認路由,這裏詳細介紹一下。假設你的註冊服務中心有三個已經註冊的服務名稱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有默認的映射機制,仍是能夠經過http://ip:port/service-c/的Url,訪問到你的service-c服務,若是不想向外界暴露默認的服務映射,能夠加上 zuul.ignored-services:*
最後,介紹一下瘋狂創客圈:瘋狂創客圈,一個Java 高併發研習社羣 【博客園 總入口 】
瘋狂創客圈,傾力推出:面試必備 + 面試必備 + 面試必備 的基礎原理+實戰 書籍 《Netty Zookeeper Redis 高併發實戰》
Java (Netty) 聊天程序【 億級流量】實戰 開源項目實戰
瘋狂創客圈 【 博客園 總入口 】
[外鏈圖片轉存中...(img-AaP9w9ZI-1571062386803)]
Java (Netty) 聊天程序【 億級流量】實戰 開源項目實戰
瘋狂創客圈 【 博客園 總入口 】