SpringCloud中的Hystrix保護(hù)機(jī)制詳解
Hystrix簡介
Hystrix,英文意思是豪豬,全身是刺,看起來就不好惹,是一種保護(hù)機(jī)制。
Hystrix也是Netflix公司的一款組件。
那么Hystix的作用是什么呢?具體要保護(hù)什么呢?
Hystix是Netflix開源的一個延遲和容錯庫,用于隔離訪問遠(yuǎn)程服務(wù)、第三方庫,防止出現(xiàn)級聯(lián)失敗。
雪崩問題
就好比,一個汽車生產(chǎn)線,生產(chǎn)不同的汽車,需要使用不同的零件,如果某個零件因?yàn)榉N種原因無法使用,那么就會造成整臺車無法裝配,陷入等待零件的狀態(tài),直到零件到位,才能繼續(xù)組裝。
此時如果有很多個車型都需要這個零件,那么整個工廠都將陷入等待的狀態(tài),導(dǎo)致所有生產(chǎn)都陷入癱瘓。
一個零件的波及范圍不斷擴(kuò)大。
Hystix解決雪崩問題的手段有兩個:
- 線程隔離
- 服務(wù)熔斷
線程隔離,服務(wù)降級
Hystrix為每個依賴服務(wù)調(diào)用分配一個小的線程池,如果線程池已滿調(diào)用將被立即拒絕,默認(rèn)不采用排隊(duì).加速失敗判定時間。
用戶的請求將不再直接訪問服務(wù),而是通過線程池中的空閑線程來訪問服務(wù),如果線程池已滿,或者請求超時,則會進(jìn)行降級處理,什么是服務(wù)降級?
服務(wù)降級:優(yōu)先保證核心服務(wù),而非核心服務(wù)不可用或弱可用。
用戶的請求故障時,不會被阻塞,更不會無休止的等待或者看到系統(tǒng)崩潰,至少可以看到一個執(zhí)行結(jié)果(例如返回友好的提示信息) 。
服務(wù)降級雖然會導(dǎo)致請求失敗,但是不會導(dǎo)致阻塞,而且最多會影響這個依賴服務(wù)對應(yīng)的線程池中的資源,對其它服務(wù)沒有響應(yīng)。
觸發(fā)Hystix服務(wù)降級的情況:
線程池已滿 請求超時
使用
使用hystrix步驟:
1.引入hystrix依賴
2.在啟動類上加@EnableCircuitBreaker注解開啟隔離和熔斷
3.配置文件 配置超時時長 不配置 也有默認(rèn)值
引入依賴
在消費(fèi)方引入依賴
<!--使用線程隔離和服務(wù)降級引入 hystrix依賴--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-hystrix</artifactId> </dependency> </dependencies>
開啟隔離
在消費(fèi)者的啟動類上
//@EnableDiscoveryClient//開啟負(fù)載均衡 //@EnableCircuitBreaker//開啟服務(wù)隔離和熔斷 //@SpringBootApplication @SpringCloudApplication//springCloud注解 包含了以上三個注解配置這個不需要配置以上三個注解 public class UserConsumerDemoApplication { @Bean @LoadBalanced//負(fù)載均衡的另一種使用方法 內(nèi)置一個攔截器 攔截所有restTemplate請求 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 { * }
編寫降級邏輯
我們改造iconsumer,當(dāng)目標(biāo)服務(wù)的調(diào)用出現(xiàn)故障,我們希望快速失敗,給用戶一個友好提示。因此需要提前編寫好失敗時的降級處理邏輯,要使用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")//開啟線程隔離和降級 fallbackMethod指定失敗方法 //類上配置了 方法上直接配置@HystrixCommand注解就行 @HystrixCommand(commandProperties = { //配置單個方法的超時時間 配置整體的超時時間需要在配置文件中配置 //設(shè)置超時時長為兩秒 @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ā)降級
@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)槿蹟嗟慕导夁壿嫹椒ū仨毟_壿嫹椒ūWC:相同的參數(shù)列表和返回值聲明。失敗邏輯中返回User對象沒有太大意義,一般會返回友好提示。所以我們把queryById的方法改造為返回String,反正也是Json數(shù)據(jù)。這樣失敗邏輯中返回一個錯誤說明,會比較方便。
設(shè)置超時
在之前的案例中,請求在超過1秒后都會返回錯誤信息,這是因?yàn)镠ystix的默認(rèn)超時時長為1,我們可以通過配置修改這個值:
yaml配置
消費(fèi)者yaml中加入
hystrix: command: default: execution: isolation: thread: timeoutInMilliseconds: 6000 # 設(shè)置hystrix的超時時間為6000ms
服務(wù)熔斷
熔斷器,也叫斷路器,其英文單詞為:Circuit Breaker 。
熔斷狀態(tài)機(jī)3個狀態(tài):
Closed:關(guān)閉狀態(tài),所有請求都正常訪問。
Open:打開狀態(tài),所有請求都會被降級。Hystix會對請求情況計(jì)數(shù),當(dāng)一定時間內(nèi)失敗請求百分比達(dá)到閾值,則觸發(fā)熔斷,斷路器會完全打開。默認(rèn)失敗比例的閾值是50%,請求次數(shù)最少不低于20次。
Half Open:半開狀態(tài),open狀態(tài)不是永久的,打開后會進(jìn)入休眠時間(默認(rèn)是5S)。隨后斷路器會自動進(jìn)入半開狀態(tài)。此時會釋放部分請求通過,若這些請求都是健康的,則會完全關(guān)閉斷路器,否則繼續(xù)保持打開,再次進(jìn)行休眠計(jì)時
為了控制請求的成功或失敗,我們在consumer的控制層中加入一段邏輯:
public String queryById(@PathVariable("id") Long id){ //因?yàn)楹茈y模擬熔斷現(xiàn)象我們只能手動控制 如果傳入的是偶數(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")//開啟線程隔離和降級 fallbackMethod指定失敗方法 //類上配置了 方法上直接配置@HystrixCommand注解就行 // @HystrixCommand(commandProperties = { //配置單個方法的超時時間 配置整體的超時時間需要在配置文件中配置 // //設(shè)置超時時長為兩秒 // @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds",value = "2000") // }) @HystrixCommand( commandProperties = { //配置單個方法的超時時間 配置整體的超時時間需要在配置文件中配置 //設(shè)置熔斷器統(tǒng)計(jì)次數(shù)為10次 @HystrixProperty(name = "circuitBreaker.requestVolumeThreshold",value = "10"), //設(shè)置休眠時間窗為10秒 @HystrixProperty(name = "circuitBreaker.sleepWindowInMilliseconds",value = "10000"), //設(shè)置錯誤百分比 為百分之六十 十次失敗六次熔斷 @HystrixProperty(name = "circuitBreaker.errorThresholdPercentage",value = "60") })
requestVolumeThreshold:觸發(fā)熔斷的最小請求次數(shù),默認(rèn)20
errorThresholdPercentage:觸發(fā)熔斷的失敗請求最小占比,默認(rèn)50%
sleepWindowInMilliseconds:休眠時長,默認(rèn)是5000毫秒
也可以在yaml配置文件中設(shè)置全局的時長
hystrix: command: #指令 default: #全局的 execution: isolation: thread: timeoutInMilliseconds: 3000 #配置全局超時時長為3秒
到此這篇關(guān)于SpringCloud中的Hystrix保護(hù)機(jī)制詳解的文章就介紹到這了,更多相關(guān)SpringCloud的Hystrix內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Apache?Commons?Config管理配置文件核心功能使用
這篇文章主要為大家介紹了Apache?Commons?Config管理和使用配置文件核心深入探索,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-12-12java利用jieba進(jìn)行分詞的實(shí)現(xiàn)
本文主要介紹了在Java中使用jieba-analysis庫進(jìn)行分詞,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2025-03-03SpringBoot項(xiàng)目引入token設(shè)置方式
本文詳細(xì)介紹了JWT(JSON Web Token)的基本概念、結(jié)構(gòu)、應(yīng)用場景以及工作原理,通過動手實(shí)踐,展示了如何在Spring Boot項(xiàng)目中實(shí)現(xiàn)JWT的生成、驗(yàn)證和攔截器配置2025-01-01SpringBoot使用Logback進(jìn)行日志記錄的代碼示例
在開發(fā)Web應(yīng)用程序時,日志記錄是非常重要的一部分,在SpringBoot中,我們可以使用Logback進(jìn)行日志記錄,Logback是一款高性能、靈活的日志框架,它可以滿足各種不同的日志需求,在本文中,我們介紹了如何在SpringBoot中使用Logback進(jìn)行日志記錄2023-06-06Java實(shí)現(xiàn)從字符串中找出數(shù)字字符串的方法小結(jié)
這篇文章主要介紹了Java實(shí)現(xiàn)從字符串中找出數(shù)字字符串的方法,結(jié)合實(shí)例形式總結(jié)分析了Java查找數(shù)字字符串的常用技巧,需要的朋友可以參考下2016-03-03Java微信二次開發(fā)(二) Java微信文本消息接口請求與發(fā)送
這篇文章主要為大家詳細(xì)介紹了Java微信二次開發(fā)第二篇,Java微信文本消息接口請求與發(fā)送功能,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-04-04springboot如何獲取yaml/yml(或properties)配置文件信息
在SpringBoot項(xiàng)目中,讀取配置文件信息是常見需求,可以通過@Autowired注入Environment類,使用@Value注解直接注入配置信息,或定義工具類結(jié)合ApplicationRunner進(jìn)行高級配置信息獲取,特別提到2024-11-11