一、概念
hystrix停止更新,理念優(yōu)秀。
分布式系統(tǒng)面臨的問題:
-
對于復(fù)雜的分布式體系,有數(shù)十個依賴,依賴不可避免的錯誤。
-
服務(wù)會出現(xiàn)雪崩,高可用受到破壞。
Hystrix就是用于解決分布式系統(tǒng)延遲和容錯的開源庫。
-
保證在一個依賴出現(xiàn)問題,不會導(dǎo)致整體的服務(wù)失敗,避免級聯(lián)故障,以提高分布式系統(tǒng)的彈性
-
如果出現(xiàn)錯誤,向調(diào)用方拋出備選FallBack
1. 功能
- 服務(wù)降級
- 服務(wù)熔斷
- 接近實時監(jiān)控
- 服務(wù)限流
- 服務(wù)隔離
停止更新進入維護
2. 重要理念
服務(wù)降級
服務(wù)器出現(xiàn)問題時候,不讓客戶端持續(xù)等待,立刻返回一個友好的提示。fallback.
以下原因會導(dǎo)致服務(wù)降級.
- 程序運行異常
- 服務(wù)熔斷觸發(fā)降級
- 線程池和信號量打滿
- 程序超時
服務(wù)熔斷
當(dāng)訪問達到最大訪問(簡短可以理解為保險絲),直接拒絕訪問,然后調(diào)用服務(wù)降級方法,返回友好提示。
降級-熔斷-恢復(fù)
服務(wù)限流
秒殺高并發(fā)的操作,嚴(yán)禁一窩蜂過來擁擠,有序進行。
二、Hystrix案例
Hystrix一般用于消費端,也就是調(diào)用端;
1. 服務(wù)降級
什么時候開啟服務(wù)降級呢?
- 當(dāng)被調(diào)用服務(wù)超時
- 當(dāng)被調(diào)用服務(wù)Down機
- 當(dāng)調(diào)用這等待時間小于服務(wù)端的處理時間
1.1 創(chuàng)建服務(wù)端
<dependencies>
<!--新增hystrix-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>com.atjianyi</groupId>
<artifactId>cloud-api-commons</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!-- <dependency>-->
<!-- <groupId>org.springframework.boot</groupId>-->
<!-- <artifactId>spring-boot-devtools</artifactId>-->
<!-- <scope>runtime</scope>-->
<!-- <optional>true</optional>-->
<!-- </dependency>-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
- 創(chuàng)建mould 8001端口,且注冊進入eureka
- 在業(yè)務(wù)當(dāng)中添加兩個方法: 方便我們后續(xù)進行服務(wù)降級和熔斷時候?qū)Ρ取?
- ok模擬正常業(yè)務(wù)
- timeout模擬長流程業(yè)務(wù)員
1.2 添加客戶端
出現(xiàn)客戶端相應(yīng)緩慢,8001同一層次的其他接口被困死,因為在tomcat線程池當(dāng)中默認只有10個線程。
客戶端服務(wù)的核心就是調(diào)用遠程服務(wù)。
使用Jemeter測試,壓測timeout方法,發(fā)現(xiàn)OK方法也出現(xiàn)了問題,相應(yīng)變慢,我們應(yīng)該怎么來改善這一問題,這就引入了我們下面要說的Hystrix;
1.3 Hystrix解決
- 超時導(dǎo)致服務(wù)器變慢
- 出錯(程序運行出錯)
解決方案:
- 對方超時,必須有服務(wù)降級
- 對方down機,必須服務(wù)降級
- 對方OK,調(diào)用者自己出故障,自己處理降級
@HystrixCommand(fallbackMethod)
EnableCirutBreaker
1.3.1 提供端降級
- 在 Timeout 業(yè)務(wù)當(dāng)中添加注解
@Override
@HystrixCommand(fallbackMethod = "timeoutHandler" ,commandProperties = {
@HystrixProperty(name="execution.isolation.thread.timeoutInMilliseconds",value = "3000") //表示業(yè)務(wù)處理若超過 3s,則降級,調(diào)用方法。
})
public String timeout(String id ) {
int tmm = 3*1000;
try {
Thread.sleep(tmm);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "payment-timeout"+"current Thread "+Thread.currentThread().getId()+" cID="+id;
}
/**
* 降級回調(diào)方法
* @param id
* @return
*/
public String timeoutHandler(String id){
return "payment-timeout-handler"+"current Thread "+Thread.currentThread().getId()+" cID="+id;
}
- 主啟動類當(dāng)中激活 @EnableCircuitBreaker
@SpringBootApplication
@EnableEurekaClient
@EnableCircuitBreaker
public class HystrixPaymentApplication {
public static void main(String[] args) {
SpringApplication.run(HystrixPaymentApplication.class,args);
}
}
測試結(jié)果
由于配置了hystrix容忍 3s 的超時,實際業(yè)務(wù)需要 5s 所以這里服務(wù)進行了降級處理。
現(xiàn)在我們把 timeout() 代碼改成如下,在進行測試: 結(jié)果顯示降級并且調(diào)用到了降級方法。
@Override
@HystrixCommand(fallbackMethod = "timeoutHandler" ,commandProperties = {
@HystrixProperty(name="execution.isolation.thread.timeoutInMilliseconds",value = "3000") //表示業(yè)務(wù)處理若超過 3s,則降級,調(diào)用方法。
})
public String timeout(String id ) {
//直接報錯,觀察是否會進行降級
int t = 10/0;
int tmm = 5*1000;
try {
Thread.sleep(tmm);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "payment-timeout"+"current Thread "+Thread.currentThread().getId()+" cID="+id;
}
1.3.2 客戶端降級
server:
port: 80
spring:
application:
name: cloud-hystrix-order
eureka:
client:
register-with-eureka: true #表示不向注冊中心注冊自己
fetch-registry: true #表示自己就是注冊中心,職責(zé)是維護服務(wù)實例,并不需要去檢索服務(wù)
service-url:
#設(shè)置與eureka server交互的地址查詢服務(wù)和注冊服務(wù)都需要依賴這個地址
defaultZone: http://localhost:7001/eureka/
# defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka
feign:
hystrix:
enabled: true
ribbon:
ReadTimeout: 5000
ConnectionTimeout: 5000
這里我們將主調(diào)用方法的超時容忍設(shè)為 1.5s, 而遠程調(diào)用的長流程業(yè)務(wù)需要 3s完成,因此,測試一樣會降級處理。
@GetMapping("consumer/payment/timeout/{id}")
@HystrixCommand(fallbackMethod = "timeoutHandler",commandProperties = {
@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds",value = "1500") //設(shè)置容忍度為1500
})
public R timeout(@PathVariable("id")String id){
R ok = paymentClient.timeout(id);
return ok;
}
public R timeoutHandler(String id){
R<String> r = new R<>();
r.setData("consumer-timeoutHandler id="+id);
return r ;
}
然而,上述代碼的寫法帶來的兩個問題
- 代碼膨脹:每個方法都有一個hystrixConnmend,若有一百個接口,就得寫一百個@hystrix…
- 代碼混亂: 服務(wù)降級和正常業(yè)務(wù)邏輯進行了混淆
針對上面出現(xiàn)的兩個問題,我們改寫為下面的方法。
1.4 全局服務(wù)降級
全局服務(wù)降級配置,就是針對需要服務(wù)降級的進行通用配置 使用 @Defaultproperties()注解進行配置;
再改寫消費端如下,配置全局服務(wù)降級;
通過上一個配置,我們解決了代碼膨脹得問題,接著我們最后寫出一套完整通用得服務(wù)調(diào)用與降級的Demo。
1.5 究極服務(wù)降級
- 在 client 接口當(dāng)中直接指定降級處理類;
- 繼承 client接口,并且實現(xiàn)方法。
在測試的時候,將 服務(wù)端(被調(diào)用端)關(guān)閉,成功調(diào)用降級方法!
這樣,我們就解決了代碼膨脹和代碼混亂的問題;
2. 服務(wù)熔斷
服務(wù)降級 -> 服務(wù)熔斷 -> 鏈路恢復(fù)
斷路器就是保險絲,熔斷: 應(yīng)對服務(wù)雪崩效應(yīng)的鏈路保護機制,當(dāng)檢測節(jié)點微服務(wù)調(diào)用響應(yīng)正常后,恢復(fù)調(diào)用鏈路。
- 熔點機制通過Hystrix實現(xiàn)
- 監(jiān)控微服務(wù)調(diào)用的狀況:
- 5秒20次調(diào)用失敗,就會啟動熔斷機制。
熔斷是> https://martinfowler.com/bliki/CircuitBreaker.html
2.1 熔斷原理
-
熔斷打開: 請求不再進行調(diào)用當(dāng)前服務(wù)
-
熔斷關(guān)閉: 熔斷關(guān)閉,不再對服務(wù)進行熔斷
-
熔斷半開: 部分請求根據(jù)規(guī)則調(diào)用當(dāng)前服務(wù),如果請求成功且符合規(guī)則,則關(guān)閉熔斷
設(shè)計斷路器的三個重要參數(shù); 快照時間窗口、請求總數(shù)閥值、錯誤百分比閥值
-
快照時間窗口: 統(tǒng)計請求和錯誤數(shù)據(jù),默認為10s內(nèi)
-
請求總數(shù)閥值: 在快照時間窗內(nèi),必須滿足請求總數(shù)才有資格熔斷,默認為20;
-
錯誤百分比法制: 當(dāng)請求總數(shù)在快照時間內(nèi)超過閥值,例如在10s內(nèi)發(fā)生30次調(diào)用,有15次失敗,則斷路器打開。
當(dāng)熔斷開啟后,直接調(diào)用fallback;
2.2 案例
- 在 payment 業(yè)務(wù)當(dāng)中,添加業(yè)務(wù)方法代碼,以便于我們測試熔斷機制。
@HystrixCommand(fallbackMethod = "paymentCircuitBreakHandler",commandProperties = {
//開啟熔斷;
@HystrixProperty(name = "circuitBreaker.enabled",value = "true"),
//請求次數(shù)至少10次
@HystrixProperty(name = "circuitBreaker.requestVolumeThreshold",value = "10"),
//在10s中
@HystrixProperty(name = "circuitBreaker.sleepWindowInMilliseconds",value = "10000"),
//錯誤率 60%
@HystrixProperty(name = "circuitBreaker.errorThresholdPercentage",value = "20")
})
public String paymentCirumentBreak(Integer id) {
if(id<0){
throw new RuntimeException("不能為負數(shù)");
}
//
String rid = UUID.randomUUID().toString().replace("-","");
return "調(diào)用成功: 流水號為: "+rid;
}
public String paymentCircuitBreakHandler(Integer id){
return "調(diào)用失敗: === 降級處理"+id;
}
-
在Controller當(dāng)中調(diào)用Service,并打開瀏覽器進行測試;
- 測試時候,傳入負數(shù)參數(shù)連續(xù)調(diào)用n次,后在傳入正數(shù),會發(fā)現(xiàn),正數(shù)返回的也是服務(wù)降級的內(nèi)容,說明斷路器Open;
- 再多次調(diào)用正數(shù)內(nèi)容,熔斷慢慢恢復(fù)到正常狀態(tài) closed;
上述熔斷過程就是 closed -> open ->halfOpen -> closed 的過程
3. 服務(wù)監(jiān)控
Hystrix還提供了一個準(zhǔn)實時的調(diào)用監(jiān)控,以報表的方式或者圖形化的方式展現(xiàn)給用戶。SpringCloud提供了hystrixDashboard的整合,對監(jiān)控內(nèi)容轉(zhuǎn)為可視化界面。
案例
- 創(chuàng)建Module
- POM
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
- yaml
Server.port=9001
- 主類激活。
- 修改被監(jiān)控的微服務(wù)
注意只要涉及到監(jiān)控,就必須要添加 actuator 依賴
再主類當(dāng)中添加如下代碼
- 訪問localhost:9001/hystrix, 監(jiān)控8001服務(wù)
在hystrix監(jiān)控欄目中輸入被監(jiān)控的地址: localhost:8001/hystrix.stream
文章來源:http://www.zghlxwxcb.cn/news/detail-470071.html
文章來源地址http://www.zghlxwxcb.cn/news/detail-470071.html
到了這里,關(guān)于Hystrix入門使用 服務(wù)熔斷 服務(wù)降級 服務(wù)雪崩的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!