微服務高可用技術
大型複雜的分布式系統中,高可用相關的技術架構非常重要。
高可用架構非常重要的一個環節,就是如何将分布式系統中的各個服務打造成高可用的服務,進而足以應對分布式系統環境中的各種各樣的問題,,避免整個分布式系統被某個服務的故障給拖垮。
比如:服務間的調用逾時 ,服務間的調用失敗
要解決這些棘手的分布式系統可用性問題,就涉及到了高可用分布式系統中的很多重要的技術,包括:
資源隔離、限流與過載保護、熔斷、優雅降級、容錯、逾時控制、監控運維
服務降級、熔斷、限流概念
服務學崩效應
服務雪崩效應産生與服務堆積在同一個線程池中,因為所有的請求都是同一個線程池進行處理,這時候如果在高并發情況下,所有的請求全部通路同一個接口,
這時候可能會導緻其他服務沒有線程進行接受請求,這就是服務雪崩效應效應。
服務降級
在高并發情況下,防止使用者一直等待,使用服務降級方式(直接傳回一個友好的提示給用戶端,調用fallBack方法)
服務熔斷
熔斷機制目的為了保護服務,在高并發的情況下,如果請求達到一定極限(可以自己設定闊值)如果流量超出了設定門檻值,讓後直接拒絕通路,保護目前服務。使用服務降級方式傳回一個友好提示,服務熔斷和服務降級一起使用
服務隔離
因為預設情況下,隻有一個線程池會維護所有的服務接口,如果大量的請求通路同一個接口,達到tomcat 線程池預設極限,可能會導緻其他服務無法通路。
解決服務雪崩效應:使用服務隔離機制(線程池方式和信号量),使用線程池方式實現隔離的原理: 相當于每個接口(服務)都有自己獨立的線程池,因為每個線程池互不影響,這樣的話就可以解決服務雪崩效應。
Hystrix簡單介紹
Hystrix是國外知名的視訊網站Netflix所開源的非常流行的高可用架構架構。Hystrix能夠完美的解決分布式系統架構中打造高可用服務面臨的一系列技術難題。
Hystrix “豪豬”,具有自我保護的能力。hystrix 通過如下機制來解決雪崩效應問題。
在微服務架構中,我們把每個業務都拆成了單個服務子產品,然後當有業務需求時,服務間可互相調用,但是,由于網絡原因或者其他一些因素,有可能出現服務不可用的情況,當某個服務出現問題時,其他服務如果繼續調用這個服務,就有可能出現線程阻塞,但如果同時有大量的請求,就會造成線程資源被用完,這樣就可能會導緻服務癱瘓,由于服務間會互相調用,很容易造成蝴蝶效應導緻整個系統宕掉。是以,就有人提出來斷路器來解決這一問題。
資源隔離:包括線程池隔離和信号量隔離,限制調用分布式服務的資源使用,某一個調用的服務出現問題不會影響其他服務調用。
降級機制:逾時降級、資源不足時(線程或信号量)降級,降級後可以配合降級接口傳回托底資料。
融斷:當失敗率達到閥值自動觸發降級(如因網絡故障/逾時造成的失敗率高),熔斷器觸發的快速失敗會進行快速恢複。
緩存:提供了請求緩存、請求合并實作。
Hystrix環境搭建
Maven依賴資訊
<!-- hystrix斷路器 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
開啟Hystrix斷路器
feign逾時時間需要設定,否則會報錯
java.net.SocketTimeoutException: Read timed out
##開啟hystrix
feign.hystrix.enabled= true
#### hystrix禁止服務逾時時間
hystrix.command.default.execution.timeout.enabled= false
#并發執行的最大線程數,預設10
#hystrix.threadpool.default.coreSize= 200
#BlockingQueue的最大隊列數,預設值-1
#hystrix.threadpool.default.maxQueueSize= 1000
#即使maxQueueSize沒有達到,達到(隊列拒絕門檻值)queueSizeRejectionThreshold該值後,請求也會被拒絕,預設值5
# hystrix.threadpool.default.queueSizeRejectionThreshold= 800
#如果并發數達到該設定值,請求會被拒絕和抛出異常并且fallback不會被調用。預設10
# hystrix.command.default.fallback.isolation.semaphore.maxConcurrentRequests= 500
@SpringBootApplication
@EnableEurekaClient
@EnableFeignClients
@EnableHystrix
public class AppOrder {
public static void main(String[] args) {
SpringApplication.run(AppOrder.class, args);
}
}
服務降級處理 注解方式
@HystrixCommand(fallbackMethod = "orderToUserInfoFallback")
@GetMapping("/orderToUserInfo")
public ResponseBase orderToUserInfoHystrix() {
System.out.println("orderToUserInfo:" + "目前線程池名稱:" + Thread.currentThread().getName());
return memberServiceFeigin.getUserInfo();
}
@RequestMapping("/orderToUserInfoFallback")
public ResponseBase orderToUserInfoFallback() {
return setResultError("系統錯誤!!!!");
}
如果每個方法都寫@HystrixCommand(fallbackMethod = "orderToUserInfoFallback")
會顯得比較麻煩,那麼如何寫個所有方法共用的呢?
使用 @[email protected]即可 直接在類上加上@DefaultProperties(defaultFallback = " orderToUserInfoFallback ") 方法上直接用@HystrixCommand就可以了
效果
當大量請求頻繁通路orderToUserInfo接口會調用orderToUserInfoFallback方法
服務降級處理 接口方式
@RequestMapping("/orderToUserInfo")
public ResponseBase orderToUserInfo() {
return memberServiceFeigin.getUserInfo();
}
@Component
public class MemberServiceFallback extends BaseApiService implements MemberServiceFeigin {
public ResponseBase getUserInfo() {
// 服務降級處理
return setResultError("系統錯誤,請稍後重試!");
}
}
Hystrix的異常處理
我們在調用服務提供者時,我們自己也有可能會抛異常,預設情況下方法拋了異常會自動進行服務降級,交給服務降級中的方法去處理。
當我們自己發生異常後,隻需要在服務降級方法中添加一個Throwable類型的參數就能夠擷取到抛出的異常的類型,如下
public String error(Throwable throwable){
System.out.println("異常資訊:"+throwable.getMessage());
//通路遠端服務失敗,該如何處理,這些處理邏輯就可以寫在該方法中 return "ERROR";
}
此時我們可以在控制台看到異常的類型; 如果遠端服務有一個異常抛出後我們不希望進入到服務降級方法中去處理,而是直接将異常抛給使用者,那麼我們可以在@HystrixCommand注解中忽略異常,如下:
@HystrixCommand(fallbackMethod="error",ignoreExceptions = Exception.class)