SpringCloud中的Hystrix保護(hù)機(jī)制詳解
Hystrix簡(jiǎn)介
Hystrix,英文意思是豪豬,全身是刺,看起來就不好惹,是一種保護(hù)機(jī)制。
Hystrix也是Netflix公司的一款組件。
那么Hystix的作用是什么呢?具體要保護(hù)什么呢?
Hystix是Netflix開源的一個(gè)延遲和容錯(cuò)庫(kù),用于隔離訪問遠(yuǎn)程服務(wù)、第三方庫(kù),防止出現(xiàn)級(jí)聯(lián)失敗。
雪崩問題
就好比,一個(gè)汽車生產(chǎn)線,生產(chǎn)不同的汽車,需要使用不同的零件,如果某個(gè)零件因?yàn)榉N種原因無法使用,那么就會(huì)造成整臺(tái)車無法裝配,陷入等待零件的狀態(tài),直到零件到位,才能繼續(xù)組裝。
此時(shí)如果有很多個(gè)車型都需要這個(gè)零件,那么整個(gè)工廠都將陷入等待的狀態(tài),導(dǎo)致所有生產(chǎn)都陷入癱瘓。
一個(gè)零件的波及范圍不斷擴(kuò)大。
Hystix解決雪崩問題的手段有兩個(gè):
- 線程隔離
- 服務(wù)熔斷
線程隔離,服務(wù)降級(jí)
Hystrix為每個(gè)依賴服務(wù)調(diào)用分配一個(gè)小的線程池,如果線程池已滿調(diào)用將被立即拒絕,默認(rèn)不采用排隊(duì).加速失敗判定時(shí)間。
用戶的請(qǐng)求將不再直接訪問服務(wù),而是通過線程池中的空閑線程來訪問服務(wù),如果線程池已滿,或者請(qǐng)求超時(shí),則會(huì)進(jìn)行降級(jí)處理,什么是服務(wù)降級(jí)?
服務(wù)降級(jí):優(yōu)先保證核心服務(wù),而非核心服務(wù)不可用或弱可用。
用戶的請(qǐng)求故障時(shí),不會(huì)被阻塞,更不會(huì)無休止的等待或者看到系統(tǒng)崩潰,至少可以看到一個(gè)執(zhí)行結(jié)果(例如返回友好的提示信息) 。
服務(wù)降級(jí)雖然會(huì)導(dǎo)致請(qǐng)求失敗,但是不會(huì)導(dǎo)致阻塞,而且最多會(huì)影響這個(gè)依賴服務(wù)對(duì)應(yīng)的線程池中的資源,對(duì)其它服務(wù)沒有響應(yīng)。
觸發(fā)Hystix服務(wù)降級(jí)的情況:
線程池已滿 請(qǐng)求超時(shí)
使用
使用hystrix步驟:
1.引入hystrix依賴
2.在啟動(dòng)類上加@EnableCircuitBreaker注解開啟隔離和熔斷
3.配置文件 配置超時(shí)時(shí)長(zhǎng) 不配置 也有默認(rèn)值
引入依賴
在消費(fèi)方引入依賴
<!--使用線程隔離和服務(wù)降級(jí)引入 hystrix依賴-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
</dependencies>開啟隔離
在消費(fèi)者的啟動(dòng)類上
//@EnableDiscoveryClient//開啟負(fù)載均衡
//@EnableCircuitBreaker//開啟服務(wù)隔離和熔斷
//@SpringBootApplication
@SpringCloudApplication//springCloud注解 包含了以上三個(gè)注解配置這個(gè)不需要配置以上三個(gè)注解
public class UserConsumerDemoApplication {
@Bean
@LoadBalanced//負(fù)載均衡的另一種使用方法 內(nèi)置一個(gè)攔截器 攔截所有restTemplate請(qǐng)求
public RestTemplate restTemplate() {
// 這次我們使用了OkHttp客戶端,只需要注入工廠即可
return new RestTemplate();
}
public static void main(String[] args) {
SpringApplication.run(UserConsumerDemoApplication.class, args);
}
}@springCloud注解源碼
* @SpringBootApplication
* @EnableDiscoveryClient
* @EnableCircuitBreaker
* public @interface SpringCloudApplication {
* }編寫降級(jí)邏輯
我們改造iconsumer,當(dāng)目標(biāo)服務(wù)的調(diào)用出現(xiàn)故障,我們希望快速失敗,給用戶一個(gè)友好提示。因此需要提前編寫好失敗時(shí)的降級(jí)處理邏輯,要使用HystixCommond來完成
消費(fèi)者的控制層中
@RestController
@RequestMapping("/consumer")
@DefaultProperties(defaultFallback = "defaultFallBack")//默認(rèn)屬性 寫在類上 類中所有方法通用屬性
public class ConsumerController {
@Autowired
private RestTemplate restTemplate;
@Autowired
private DiscoveryClient discoveryClient;
@GetMapping("{id}")
@HystrixCommand(fallbackMethod = "queryByIdFallBack")//開啟線程隔離和降級(jí) fallbackMethod指定失敗方法
//類上配置了 方法上直接配置@HystrixCommand注解就行
@HystrixCommand(commandProperties = { //配置單個(gè)方法的超時(shí)時(shí)間 配置整體的超時(shí)時(shí)間需要在配置文件中配置
//設(shè)置超時(shí)時(shí)長(zhǎng)為兩秒
@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds",value = "2000")
})
public String queryById(@PathVariable("id") Long id){
String url="http://user-service/user/"+id;
String user = restTemplate.getForObject(url, String.class);
return user;
}
//失敗方法和成功方法 參數(shù) 返回值必須一樣 方法名不做限制
public String queryByIdFallBack(Long id){
return "服務(wù)正忙,稍后重試";
}
//在方法上配置寫參數(shù) 在類上配置通用的 不能寫參數(shù)
public String defaultFallBack(){
return "服務(wù)正忙,稍后重試";
}改造服務(wù)提供者
改造userservice的控制層 觸發(fā)降級(jí)
@GetMapping("{id}")
public User queryUserById(@PathVariable("id") Long id) {
try {
Thread.sleep(6000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return this.userService.queryUserById(id);
}
要注意,因?yàn)槿蹟嗟慕导?jí)邏輯方法必須跟正常邏輯方法保證:相同的參數(shù)列表和返回值聲明。失敗邏輯中返回User對(duì)象沒有太大意義,一般會(huì)返回友好提示。所以我們把queryById的方法改造為返回String,反正也是Json數(shù)據(jù)。這樣失敗邏輯中返回一個(gè)錯(cuò)誤說明,會(huì)比較方便。
設(shè)置超時(shí)
在之前的案例中,請(qǐng)求在超過1秒后都會(huì)返回錯(cuò)誤信息,這是因?yàn)镠ystix的默認(rèn)超時(shí)時(shí)長(zhǎng)為1,我們可以通過配置修改這個(gè)值:
yaml配置
消費(fèi)者yaml中加入
hystrix:
command:
default:
execution:
isolation:
thread:
timeoutInMilliseconds: 6000 # 設(shè)置hystrix的超時(shí)時(shí)間為6000ms
服務(wù)熔斷
熔斷器,也叫斷路器,其英文單詞為:Circuit Breaker 。
熔斷狀態(tài)機(jī)3個(gè)狀態(tài):
Closed:關(guān)閉狀態(tài),所有請(qǐng)求都正常訪問。
Open:打開狀態(tài),所有請(qǐng)求都會(huì)被降級(jí)。Hystix會(huì)對(duì)請(qǐng)求情況計(jì)數(shù),當(dāng)一定時(shí)間內(nèi)失敗請(qǐng)求百分比達(dá)到閾值,則觸發(fā)熔斷,斷路器會(huì)完全打開。默認(rèn)失敗比例的閾值是50%,請(qǐng)求次數(shù)最少不低于20次。
Half Open:半開狀態(tài),open狀態(tài)不是永久的,打開后會(huì)進(jìn)入休眠時(shí)間(默認(rèn)是5S)。隨后斷路器會(huì)自動(dòng)進(jìn)入半開狀態(tài)。此時(shí)會(huì)釋放部分請(qǐng)求通過,若這些請(qǐng)求都是健康的,則會(huì)完全關(guān)閉斷路器,否則繼續(xù)保持打開,再次進(jìn)行休眠計(jì)時(shí)
為了控制請(qǐng)求的成功或失敗,我們?cè)赾onsumer的控制層中加入一段邏輯:
public String queryById(@PathVariable("id") Long id){
//因?yàn)楹茈y模擬熔斷現(xiàn)象我們只能手動(dòng)控制 如果傳入的是偶數(shù)就熔斷 如果是技術(shù)就恢復(fù)正常
if(id%2==0){
throw new RuntimeException("");
}
String url="http://user-service/user/"+id;
String user = restTemplate.getForObject(url, String.class);
return user;
}@GetMapping("{id}")
// @HystrixCommand(fallbackMethod = "queryByIdFallBack")//開啟線程隔離和降級(jí) fallbackMethod指定失敗方法
//類上配置了 方法上直接配置@HystrixCommand注解就行
// @HystrixCommand(commandProperties = { //配置單個(gè)方法的超時(shí)時(shí)間 配置整體的超時(shí)時(shí)間需要在配置文件中配置
// //設(shè)置超時(shí)時(shí)長(zhǎng)為兩秒
// @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds",value = "2000")
// })
@HystrixCommand(
commandProperties = { //配置單個(gè)方法的超時(shí)時(shí)間 配置整體的超時(shí)時(shí)間需要在配置文件中配置
//設(shè)置熔斷器統(tǒng)計(jì)次數(shù)為10次
@HystrixProperty(name = "circuitBreaker.requestVolumeThreshold",value = "10"),
//設(shè)置休眠時(shí)間窗為10秒
@HystrixProperty(name = "circuitBreaker.sleepWindowInMilliseconds",value = "10000"),
//設(shè)置錯(cuò)誤百分比 為百分之六十 十次失敗六次熔斷
@HystrixProperty(name = "circuitBreaker.errorThresholdPercentage",value = "60")
})requestVolumeThreshold:觸發(fā)熔斷的最小請(qǐng)求次數(shù),默認(rèn)20
errorThresholdPercentage:觸發(fā)熔斷的失敗請(qǐng)求最小占比,默認(rèn)50%
sleepWindowInMilliseconds:休眠時(shí)長(zhǎng),默認(rèn)是5000毫秒
也可以在yaml配置文件中設(shè)置全局的時(shí)長(zhǎng)
hystrix:
command: #指令
default: #全局的
execution:
isolation:
thread:
timeoutInMilliseconds: 3000 #配置全局超時(shí)時(shí)長(zhǎng)為3秒到此這篇關(guān)于SpringCloud中的Hystrix保護(hù)機(jī)制詳解的文章就介紹到這了,更多相關(guān)SpringCloud的Hystrix內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java中如何將String轉(zhuǎn)JSONObject
這篇文章主要介紹了Java中如何將String轉(zhuǎn)JSONObject,String類型轉(zhuǎn)JSONObject,下面有兩種方式可以進(jìn)行轉(zhuǎn)換,本文結(jié)合實(shí)例代碼給大家介紹的非常詳細(xì),需要的朋友可以參考下2023-05-05
Spring?Boot中WebMvcConfig配置詳解及示例代碼
WebMvcConfig是一個(gè)配置類,它繼承了WebMvcConfigurationSupport,允許我們對(duì)SpringMVC進(jìn)行更細(xì)粒度的控制,這篇文章主要給大家介紹了關(guān)于Spring?Boot中WebMvcConfig配置詳解及示例的相關(guān)資料,需要的朋友可以參考下2024-03-03
SSO單點(diǎn)登錄系統(tǒng)實(shí)現(xiàn)原理及流程圖解
這篇文章主要介紹了SSO單點(diǎn)登錄系統(tǒng)實(shí)現(xiàn)原理及流程圖解,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-12-12
什么情況下會(huì)出現(xiàn)java.io.IOException?:?Broken?pipe這個(gè)錯(cuò)誤以及解決辦法
這篇文章主要介紹了什么情況下會(huì)出現(xiàn)java.io.IOException?:?Broken?pipe這個(gè)錯(cuò)誤以及解決辦法的相關(guān)資料,這個(gè)錯(cuò)誤表示通信另一端已關(guān)閉連接,常發(fā)生在客戶端關(guān)閉連接、網(wǎng)絡(luò)超時(shí)或資源不足等情況,文中將解決辦法介紹的非常詳細(xì),需要的朋友可以參考下2024-10-10
SpringBoot 圖形驗(yàn)證碼的生成和校驗(yàn)
隨著系統(tǒng)和業(yè)務(wù)的不停升級(jí),前后端代碼放在一起的項(xiàng)目越來越臃腫,已經(jīng)無法快速迭代和職責(zé)區(qū)分了,于是紛紛投入了前后端分離的懷抱,發(fā)現(xiàn)代碼和職責(zé)分離以后,開發(fā)效率越來越高了,但是以前的驗(yàn)證碼登錄方案就要更改了。本文來看一下SpringBoot 圖形驗(yàn)證碼的生成和校驗(yàn)2021-05-05
SpringBoot+Spring?Data?JPA整合H2數(shù)據(jù)庫(kù)的示例代碼
H2數(shù)據(jù)庫(kù)是一個(gè)開源的關(guān)系型數(shù)據(jù)庫(kù),本文重點(diǎn)給大家介紹SpringBoot+Spring?Data?JPA整合H2數(shù)據(jù)庫(kù)的示例代碼,感興趣的朋友跟隨小編一起看看吧2022-02-02
java發(fā)送heartbeat心跳包(byte轉(zhuǎn)16進(jìn)制)
這篇文章主要介紹了java發(fā)送heartbeat心跳包(byte轉(zhuǎn)16進(jìn)制),需要的朋友可以參考下2014-05-05

