javascript
Spring Cloud 入门 之 Hystrix 篇(四)
一、前言
在微服務應用中,服務存在一定的依賴關系,如果某個目標服務調用慢或者有大量超時造成服務不可用,間接導致其他的依賴服務不可用,最嚴重的可能會阻塞整條依賴鏈,最終導致業務系統崩潰(又稱雪崩效應)。
上述的問題將是本篇需要解決的問題。
二、簡單介紹
#?2.1 請求熔斷
斷路器是一種開關設置,當某個服務單元發生故障之后,通過斷路器的故障監控,向調用方返回一個符合預期的服務降級處理(fallback),而不是長時間的等待或者拋出調用方無法處理的異常,這樣保證了服務調用方的線程不會長時間被占用,從而避免了故障在分布式系統的蔓延乃至崩潰。
#?2.2 服務降級
fallback 相當于是降級操作。對于查詢操作, 我們可以實現一個 fallback 方法, 當請求后端服務出現異常的時候, 可以使用 fallback 方法返回的值。 fallback 方法的返回值一般是設置的默認值或者來自緩存,告知后面的請求服務不可用了,不要再請求了。
#?2.3 請求熔斷和服務降級區別
- 相同:
- 不同:
#?2.4 實現方案
Spring Cloud Hystrix 實現了斷路器、線程隔離等一系列服務保護功能。它是基于 Netflix 的開源框架 Hystrix 實現的,該框架的目的在于通過控制訪問遠程系統、服務和第三方庫節點,從而對延遲和故障提供更強大的容錯能力。
Hystrix 具備服務熔斷、服務降級、線程和信號隔離、請求緩存、請求合并以及服務監控的能力。
三、請求熔斷實戰
本次測試案例基于之前發表的文章中介紹的案例進行演示,不清楚的讀者請先轉移至?《Spring Cloud 入門 之 Feign 篇(三)》?進行瀏覽。
現在的項目列表如下:
| common-api | - | 公用的 api,如:實體類 |
| eureka-server | 9000 | 注冊中心(Eureka 服務端) |
| goods-server | 8081 | 商品服務(Eureka 客戶端) |
| goods-server-02 | 8082 | 商品服務(Eureka 客戶端) |
| goods-server-03 | 8083 | 商品服務(Eureka 客戶端) |
| order-server | 8100 | 訂單服務(Eureka 客戶端) |
在 order-server 項目中:
#?3.1 添加依賴
<!-- hystrix --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-hystrix</artifactId> </dependency>#?3.2 設置熔斷策略
我們來修改獲取下訂單的方法,在 placeOrder 方法上加?@HystrixCommand?注解:
@Service public class OrderServiceImpl implements OrderService{@Autowired private RestTemplate restTemplate;// @Autowired // private GoodsServiceClient goodsServiceClient;@HystrixCommand(fallbackMethod = "defaultByPlaceOrder") @Override public void placeOrder(Order order) throws Exception{Result result = this.restTemplate.getForObject("http://GOODS/goods/goodsInfo/" + order.getGoodsId(), Result.class);// Result result = this.goodsServiceClient.goodsInfo(order.getGoodsId());if (result != null && result.getCode() == 200) { System.out.println("=====下訂單===="); System.out.println(result.getData()); } else { System.out.println(result.getMsg()); } }public void defaultByPlaceOrder(Order order) { System.out.println("商品服務系統異常"); } }當調用商品服務超時或出現異常時,Hystrix 會調用?@HystrixCommand?中指定的 fallbackMethod 方法獲取返回值或執行異常處理。
注意:fallbackMethod 方法要求與正常方法有相同的入參和回參。
#?3.3 啟動熔斷功能
在啟動類上添加?@EnableCircuitBreaker?注解:
@EnableCircuitBreaker @EnableEurekaClient @SpringBootApplication public class OrderServerApplication {public static void main(String[] args) { SpringApplication.run(OrderServerApplication.class, args); } }#?3.4 熔斷測試
啟動好所有項目,使用 Postman 請求 order-server 進行下單操作,運行結果如下:
當我們請求發送的 goodsId 的商品不存在,服務提供方拋會異常,調用方無法處理,因此只能展示圖中的異常信息。
? ? 2. 下面,我們再將?@EnableCircuitBreaker?注解的注釋放開,運行結果如下:
從圖中可知,雖然請求了一個 goodsId 不存在的商品,但是調用方(order-server)開啟了熔斷機制,執行默認方法,從而使接口能正常通信而不是拋出調用方不可處理的異常導致整個系統不能正常運行。
看到這里,或許會有讀者產生一個疑問,如果類中定義 N 個方法,是不是意味著同時也要定義 N 個異常處理的方法呢,答案是否定的。
Hystrix 還提供了?@DefaultProperties?統一處理請求熔斷,在該注解上設置?defaultFallback?屬性值,即熔斷開啟后要執行的方法。
@Service @DefaultProperties(defaultFallback = "defaultByHystrix") public class OrderServiceImpl implements OrderService{// @Autowired // private RestTemplate restTemplate;@Autowired private GoodsServiceClient goodsServiceClient;@HystrixCommand @Override public void placeOrder(Order order) throws Exception{// Result result = this.restTemplate.getForObject("http://GOODS/goods/goodsInfo/" + order.getGoodsId(), Result.class);Result result = this.goodsServiceClient.goodsInfo(order.getGoodsId());if (result != null && result.getCode() == 200) { System.out.println("=====下訂單===="); System.out.println(result.getData()); } else { System.out.println(result.getMsg()); } }public void defaultByHystrix() { System.out.println("商品服務系統異常"); } }注意:defaultFallback 定義的方法必須是無參的。
四、服務降級實戰
在 common-api 項目中:
#?4.1 定義 Fallback
@Component public class GoodsServiceClientFallbackFactory implements FallbackFactory<GoodsServiceClient> {@Override public GoodsServiceClient create(Throwable cause) { return new GoodsServiceClient() {@Override public Result goodsInfo(String goodsId) { return Result.fail(500, "商品服務系統出現異常,請聯系管理員"); }}; }}使用單獨的類處理異常邏輯,當與服務端無法正常通信時調用此類中的方法返回結果。
#?4.2 修改 Feign 客戶端
將上邊定義好的 FallbackFactory 設置到?@FeignClient?注解上:
@FeignClient(value="GOODS", fallbackFactory = GoodsServiceClientFallbackFactory.class) public interface GoodsServiceClient {@RequestMapping("/goods/goodsInfo/{goodsId}") public Result goodsInfo(@PathVariable("goodsId") String goodsId); }#?4.3 開啟服務降級功能
在 order-server 項目中:
server: port: 8100spring: application: name: ORDEReureka: instance: instance-id: order-api-8100 prefer-ip-address: true # 訪問路徑可以顯示 IP client: service-url: defaultZone: http://localhost:9000/eureka/ # 注冊中心訪問地址feign: hystrix: enabled: true#?4.4 去掉 @HystrixCommand 配置
@Service //@DefaultProperties(defaultFallback = "defaultByHystrix") public class OrderServiceImpl implements OrderService{// @Autowired // private RestTemplate restTemplate;@Autowired private GoodsServiceClient goodsServiceClient;// @HystrixCommand @Override public void placeOrder(Order order) throws Exception{// Result result = this.restTemplate.getForObject("http://GOODS/goods/goodsInfo/" + order.getGoodsId(), Result.class);Result result = this.goodsServiceClient.goodsInfo(order.getGoodsId());if (result != null && result.getCode() == 200) { System.out.println("=====下訂單===="); System.out.println(result.getData()); } else { System.out.println(result.getMsg()); } }// public void defaultByHystrix() { // System.out.println("商品服務系統異常"); // } }#?4.5 測試服務降級
在啟動類上加 FallbackFactory 類的包掃描目錄:
@ComponentScan(basePackages = {"com.extlight.springcloud"}) // 為了能掃描 common-api 項目中的 GoodsServiceClientFallbackFactory @EnableFeignClients(basePackages = {"com.extlight.springcloud"}) @EnableEurekaClient @SpringBootApplication public class OrderServerApplication {public static void main(String[] args) { SpringApplication.run(OrderServerApplication.class, args); } }打開 Postman 請求下單接口,結果如下圖:
我們手動關閉 2 個商品服務,保留一個商品服務并多次請求商品服務接口,從而出模擬商品服務超過預定荷載情景,最終看到圖中服務降級功能。當有請求再次訪問商品服務時默認返回?GoodsServiceClientFallbackFactory?中定義的內容。
五、儀表盤
除了服務熔斷、降級的功能外,Hystrix 還提供了準及時的調用監控。 Hystrix 會持續地記錄所有通過 Hystrix 發起的請求的執行信息,并以統計報表和圖形方式展示給用戶。
#?5.1 配置被監控方
order-server 項目中:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency>修改 application.yml,開放端口:
management: endpoints: web: exposure: include: "*"#?5.2 配置監控方
1.新建一個名為 hystrix-dashboard 項目,添加如下依賴:
<!-- hystrix-dashboard --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId> </dependency>2.新建 application.yml
server: port: 9300spring: application: name: Hystrix-Dashboard3.開啟監控功能
在啟動類上添加?@EnableHystrixDashboard?注解。
@EnableHystrixDashboard @SpringBootApplication public class HystrixdashboardApplication {public static void main(String[] args) { SpringApplication.run(HystrixdashboardApplication.class, args); } }啟動,瀏覽器訪問:?http://localhost:9300/hystrix:
#?5.3 監控設置
我們以監控 order-server 為例,在監控界面添加監控信息:
# 需要監控的服務地址 http://localhost:8100/actuator/hystrix.streamdelay: 請求間隔時間title: 監控名稱點擊 monitor stream批量訪問 order-server 服務的下單接口。最終效果如下:
通過批量訪問下單接口,發現圖中實心圓和曲線發生了變化。那我們如何根據這兩個圖形查看監控信息呢?
實心圓:通過顏色的變化代表實例的健康程度,健康度從綠色>黃色>橙色>紅色遞減。其大小也會根據實例的請求流量發生變化,流量越大實心圓越大。
曲線:用來記錄間隔時間內流量的相對變化,通常可以觀察到流量的上升和下降趨勢。
六、案例源碼
Hystrix demo 源碼
七、參考資料
hystrix-javanica
hystrix configuration
hystrix dashboard
?
新人創作打卡挑戰賽發博客就能抽獎!定制產品紅包拿不停!總結
以上是生活随笔為你收集整理的Spring Cloud 入门 之 Hystrix 篇(四)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: hdu 1593(数学)
- 下一篇: Spring Cloud 入门 之 Ri