springcloud使用Hystrix進(jìn)行微服務(wù)降級管理
前言:目前我們的項目是微服務(wù)架構(gòu),基于dubbo框架,服務(wù)之間的調(diào)用是通過rpc調(diào)用的。剛開始沒有任何問題,項目運(yùn)行健康、良好??墒沁^了一段時間,線上總有人反應(yīng)查詢訂單失敗,等過了一段時間才能查到。這是怎么回事呢?打開后臺的日志一看出現(xiàn)了一些RpcException和TimeOutException,原來是遠(yuǎn)程調(diào)用超時了,可能某個服務(wù)在請求的高發(fā)期訪問數(shù)據(jù)庫異常,IO阻塞,返回接口異常了。后來這個問題越來越頻繁,如何解決這個棘手的問題呢?
一:Hystrix是什么?
1.1:基本解釋
Hystrix最開始由Netflix(看過美劇的都知道,它是一個美劇影視制作的巨頭公司)開源的,后來由Spring Cloud Hystrix基于這款框架實現(xiàn)了斷路器、線程隔離等一系列服務(wù)保護(hù)功能,該框架的目標(biāo)在于通過控制訪問遠(yuǎn)程系統(tǒng)、服務(wù)和第三方庫的節(jié)點,從而延遲和故障提供更強(qiáng)大的容錯能力。hystrix具備服務(wù)降級、服務(wù)熔斷、線程和信號隔離、請求緩存、請求合并以及服務(wù)監(jiān)控等強(qiáng)大功能。起到了微服務(wù)的保護(hù)機(jī)制,防止某個單元出現(xiàn)故障.從而引起依賴關(guān)系引發(fā)故障的蔓延,最終導(dǎo)致整個系統(tǒng)的癱瘓。
1.2:斷路器的概念
斷路器本身是一個開關(guān)裝置,用在電路上保護(hù)線路過載,當(dāng)線路中有電器發(fā)生短路的時候。“斷路器”能夠及時切斷故障,防止發(fā)生過載、發(fā)熱甚至起火等嚴(yán)重后果。當(dāng)分布式架構(gòu)中,斷路器模式起到的作用也是類似的。當(dāng)某個服務(wù)發(fā)生故障的時候,通過斷路器的故障監(jiān)控向調(diào)用方返回一個錯誤響應(yīng),而不是長時間的線程掛機(jī),無限等待。這樣就不會使線程因故障服務(wù)被長時間占用不釋放,避免了故障在分布式系統(tǒng)中的蔓延。如下圖是現(xiàn)實中的斷路器,它是一個開關(guān)裝置:

二:Hystrix解決超時問題
2.1:問題
假設(shè)我們前端提供了用戶查詢訂單的功能,首先請求映射到OrderController,控制器通過調(diào)用服務(wù)orderService獲取訂單信息,前端傳過來兩個參數(shù):一個是訂單id,一個是用戶id,orderService需要通過用戶id調(diào)取用戶服務(wù)來獲取用戶的相關(guān)信息返回給訂單服務(wù)去組裝信息,假設(shè)這里是通過http請求的,我們有一個單獨的工程叫做:userService部署在其他的服務(wù)器上。但是這個服務(wù)器宕機(jī)了,這時候訂單服務(wù)調(diào)取用戶信息就失敗了,然后查詢訂單整個請求就失敗了!由一個服務(wù)的宕機(jī)就導(dǎo)致整個查詢都失敗了,牽一發(fā)而動全身。流程見下圖:

2.2:使用Hystrix進(jìn)行服務(wù)降級
2.2.1:引入hystrix依賴 這里引入了spring-cloud-starter-netflix-hystrix,springboot的starter里面整合了hystrix
<properties>
<java.version>1.8</java.version>
<spring-cloud.version>Greenwich.SR1</spring-cloud.version>
</properties>
<dependencies>
<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-hystrix-dashboard</artifactId>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>4.5.1</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
2.2.2:模擬訂單請求
首先通過OrderController映射/order請求,獲取前端傳入的參數(shù)orderId和useId,然后調(diào)用orderDetailService方法,
@RestController
public class OrderController {
@Resource
private OrderService orderService;
/**
* 獲取訂單信息
*
* @param orderNo
* @return
*/
@PostMapping("/order")
public ResultVo<OrderDetail> getOrderInfo(@RequestParam("orderId") Long orderNo, @RequestParam("userId") Long userId) {
OrderDetail orderDetail = orderService.orderDetailService(orderNo, userId);
ResultVo resultVo = new ResultVo<>();
resultVo.setCode(100);
resultVo.setMessage("請求成功");
resultVo.setData(orderDetail);
return resultVo;
}
}
2.2.3:訂單服務(wù)調(diào)取其他服務(wù)
這里引入了RestTemplate,它是一個spring封裝的http映射請求工具類,然后通過http請求訪問url = "http://192.168.80.153:8070/user/getUser"獲取用戶名,將值給訂單對象。不過假如在這其中發(fā)生了調(diào)用異常,請求用戶服務(wù)異常的話,那么返回給前端就是一串空的訂單信息,導(dǎo)致用戶看到的訂單為空。在使用hystrix之后,可以用@HystrixCommand(fallbackMethod = "orderFallBack")注解,在fallbackMethod中指定回退的方法,這里必須注意在@HystrixCommand上的方法其指定的回調(diào)方法必須和原方法的參數(shù)保持一致,這里包括參數(shù)類型、參數(shù)個數(shù)、參數(shù)順序。我們在回調(diào)用法中模擬去查詢緩存數(shù)據(jù),返回給訂單。有人又要問了,如果查詢緩存服務(wù)器再異常呢?不排除這種可能性。如果是這樣的話,依然可以使用@HystrixCommand注解在回調(diào)方法中,再指定其他的回調(diào)方法:
@Service
public class OrderService {
@Autowired
private RestTemplate restTemplate;
/**
* 根據(jù)訂單id獲取訂單詳情
*
* @param orderId
* @param userId
* @return
*/
@HystrixCommand(fallbackMethod = "orderFallBack")
public OrderDetail orderDetailService(Long orderId, Long userId) {
if (Objects.isNull(orderId)) {
return null;
}
OrderDetail orderDetail = OrderDBSource.getOrderDB().get(orderId);
//調(diào)用user服務(wù)
final String url = "http://192.168.80.153:8070/user/getUser";
String userName = "";
ResponseEntity<String> responseEntity = restTemplate.postForEntity(url, userId, String.class);
String returnContent = responseEntity.getBody();
if (Objects.nonNull(responseEntity) && StrUtil.isNotEmpty(returnContent)) {
userName = returnContent;
}
if (ObjectUtil.isNotNull(orderDetail)){
orderDetail.setUserName(userName);
}
return orderDetail;
}
/**
* 異常調(diào)用的回調(diào)方法
*
* @return
*/
public OrderDetail orderFallBack(Long orderId, Long userId) {
OrderDetail orderDetail = OrderDBSource.getOrderCache().get(orderId);
final String unknown = "未知用戶";
orderDetail.setUserName(unknown);
return orderDetail;
}
}
2.3.4:模擬測試
為了方便測試,首先我們將請求服務(wù)暫時先注釋,然后用postman測試看正常的返回應(yīng)該是這樣的,這里使用了備注為數(shù)據(jù)庫獲取的訂單,表明它沒有走回調(diào)方法,因為這里沒有訪問用戶url獲取用戶信息,程序可以正常訪問。我再放開

加上獲取用戶服務(wù)的鏈接,實際上用戶服務(wù)是無法訪問到的,訪問的話就會超時,超時會被hystrix捕捉到,然后走fallBack指定的方法,我們來測試一下,可以看到實際上走的是緩存中查詢到的訂單,可以看到用戶服務(wù)已經(jīng)成功的降級了,降級后的訂單信息雖然是緩存獲取到的,可能會存在延時等問題(當(dāng)然只要維護(hù)好緩存就可以避免這個問題)。但是比沒有任何數(shù)據(jù)帶來的用戶一點會更好!

三:Hystrix的流程
Hystrix實際上的工作原理是這樣的:通過command來解耦請求與返回操作,在具體的實例中就是,Hystrix會對依賴的服務(wù)進(jìn)行觀察,通過command.toObservable調(diào)用返回一個觀察的對象,同時發(fā)起一個事件,然后用Subscriber對接受到的事件進(jìn)行處理。在command命令發(fā)出請求后,它通過一系列的判斷,順序依次是緩存是否命中、斷路器是否打開、線程池是否占滿,然后它才會開始對我們編寫的代碼進(jìn)行實際的請求依賴服務(wù)的處理,也就是Hystrix.run方法,如果在這其中任一節(jié)點出現(xiàn)錯誤或者拋出異常,它都會返回到fallback方法進(jìn)行服務(wù)降級處理,當(dāng)降級處理完成之后,它會將結(jié)果返回給,際的調(diào)用者,經(jīng)過一系列流程處理的,它的具體工作流程如下:

四:總結(jié)
本篇博客講述了Hystrix是什么?然后解釋了Hystrix如何進(jìn)行服務(wù)降級處理以及簡單的處理流程,講到的內(nèi)容是最為常用的功能,還有一些關(guān)于Hystrix的緩存、線程池的隔離技術(shù)等由于篇幅的原因,沒有詳細(xì)的講解到,不過作為一篇入門級的Hystrix教程博客是基本夠的。在實際的開發(fā)中,如何保持服務(wù)的健壯性、服務(wù)的可用性、盡量的減少bug,提升用戶體驗都是我們開發(fā)者的使命,這條優(yōu)化和提升之路永遠(yuǎn)沒有盡頭,go ahead!
參考資料《spring cloud微服務(wù)實戰(zhàn)》
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- SpringCloud Feign隔離與降級詳細(xì)分析
- SpringCloud hystrix服務(wù)降級學(xué)習(xí)筆記
- SpringCloud?hystrix斷路器與局部降級全面介紹
- SpringCloud hystrix服務(wù)降級概念介紹
- SpringCloud降級規(guī)則使用介紹
- SpringCloud-Alibaba-Sentinel服務(wù)降級,熱點限流,服務(wù)熔斷
- springcloud 服務(wù)降級的實現(xiàn)方法
- 詳解springcloud 基于feign的服務(wù)接口的統(tǒng)一hystrix降級處理
- SpringCloud災(zāi)難性雪崩效應(yīng)處理方法之降級實現(xiàn)流程詳解
相關(guān)文章
SpringBoot自定義對象參數(shù)實現(xiàn)自動類型轉(zhuǎn)換與格式化
SpringBoot 通過自定義對象參數(shù),可以實現(xiàn)自動類型轉(zhuǎn)換與格式化,并可以級聯(lián)封裝,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)吧2022-09-09
springboot使用自定義注解實現(xiàn)aop切面日志
這篇文章主要為大家詳細(xì)介紹了springboot使用自定義注解實現(xiàn)aop切面日志,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下2022-09-09
Spring?Boot?整合持久層之Spring Data JPA
在介紹Spring Data JPA的時候,我們首先認(rèn)識下Hibernate。Hibernate是數(shù)據(jù)訪問解決技術(shù)的絕對霸主,使用O/R映射技術(shù)實現(xiàn)數(shù)據(jù)訪問,O/R映射即將領(lǐng)域模型類和數(shù)據(jù)庫的表進(jìn)行映射,通過程序操作對象而實現(xiàn)表數(shù)據(jù)操作的能力,讓數(shù)據(jù)訪問操作無須關(guān)注數(shù)據(jù)庫相關(guān)的技術(shù)2022-08-08
Java關(guān)鍵字synchronized原理與鎖的狀態(tài)詳解
在Java當(dāng)中synchronized關(guān)鍵字通常是用來標(biāo)記一個方法或者代碼塊。本文將通過示例為大家詳細(xì)介紹一下Synchronized的各種使用方法,需要的可以參考一下2022-08-08

