【SpringCloud】Hystrix服務降級(十)


Hystrix介紹  

  Hystrix是一個用於處理分布式系統的延遲和容錯的開源庫,在分布式系統里,許多依賴不可避免的會調用失敗,比如超時、異常等,Hystrix能保證在一個依賴出問題的情況下,不會導致整體服務失敗,避免級聯故障,以提高分布式系統的彈性。

  “斷路器”本身是一種開關裝置,當某個服務單元發生故障之后,通過斷路器的故障監控(類似熔斷保險絲),向調用方返回一個符合預期的、可處理的備選響應(FallBack),而不長時間的等待或者拋出調用方法無法處理的異常,這樣就保證了服務調用方的線程不會被長時間、不必要地占用,從而避免了故障在分布式系統中的蔓延,乃至雪崩。

  github地址:https://github.com/Netflix/Hystrix

  服務降級  

  所謂降級,就是當某個服務出現異常之后,服務器將不再被調用,此時服務端可以自己准備一個本地的fallback回調,返回一個缺省值。 這樣做,雖然服務水平下降,但好歹可用,比直接掛掉要強,當然這也要看適合的業務場景。

  可能出現服務降級的情況:

  • 程序運行異常
  • 服務超時
  • 服務熔斷出發服務降級
  • 線程池/信號量打滿也會導致服務降級

Hystrix使用

  項目准備

  搭建項目,本章采用的項目框架如下:

  

  參考:【SpringCloud】快速入門(一)

服務降級Fallback

  1、在服務提供者模塊(test-springcloud-provider-payment8008)中,引入Hystrix的依賴:

1 <!-- hystrix -->
2 <dependency>
3     <groupId>org.springframework.cloud</groupId>
4     <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
5 </dependency>

    完整pom如下:

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <project xmlns="http://maven.apache.org/POM/4.0.0"
 3          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 4          xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
 5     <parent>
 6         <artifactId>test-springcloud</artifactId>
 7         <groupId>com.test</groupId>
 8         <version>1.0-SNAPSHOT</version>
 9     </parent>
10     <modelVersion>4.0.0</modelVersion>
11 
12     <artifactId>test-springcloud-provider-payment8008</artifactId>
13 
14     <dependencies>
15 
16         <!-- hystrix -->
17         <dependency>
18             <groupId>org.springframework.cloud</groupId>
19             <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
20         </dependency>
21 
22         <!-- eureka client -->
23         <dependency>
24             <groupId>org.springframework.cloud</groupId>
25             <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
26         </dependency>
27 
28         <!-- spring boot -->
29         <dependency>
30             <groupId>org.springframework.boot</groupId>
31             <artifactId>spring-boot-starter-web</artifactId>
32         </dependency>
33         <dependency>
34             <groupId>org.springframework.boot</groupId>
35             <artifactId>spring-boot-starter-actuator</artifactId>
36         </dependency>
37 
38         <dependency>
39             <groupId>org.springframework.boot</groupId>
40             <artifactId>spring-boot-devtools</artifactId>
41             <scope>runtime</scope>
42             <optional>true</optional>
43         </dependency>
44 
45         <dependency>
46             <groupId>org.projectlombok</groupId>
47             <artifactId>lombok</artifactId>
48             <optional>true</optional>
49         </dependency>
50         <dependency>
51             <groupId>org.springframework.boot</groupId>
52             <artifactId>spring-boot-starter-test</artifactId>
53             <scope>test</scope>
54         </dependency>
55 
56     </dependencies>
57 
58     <build>
59         <finalName>test-springcloud-provider-payment8008</finalName>
60     </build>
61 </project>
View Code

  2、配置文件如下:

 1 # 端口
 2 server:
 3   port: 8008
 4 
 5 spring:
 6   application:
 7     name: cloud-payment-service
 8 
 9 eureka:
10   client:
11     service-url:
12       defaultZone: http://localhost:8761/eureka
13   instance:
14     #  instance:
15     instance-id: ${spring.cloud.client.ip-address}:${server.port}
16     # 訪問路徑可以顯示IP地址
17     prefer-ip-address: true

  3、編輯啟動類,使用注解@EnableCircuitBreaker,允許斷路器

1 @SpringBootApplication
2 @EnableEurekaClient
3 //允許斷路器
4 @EnableCircuitBreaker
5 public class PaymentMain8008 {
6     public static void main(String[] args) {
7         SpringApplication.run(PaymentMain8008.class, args);
8     }
9 }

  4、編輯業務類,並在方法上使用@HystrixCommand注解,表明方法支持服務降級,且設置了超時的降級策略

 1 @Service
 2 public class PaymentService {
 3 
 4     public String paymentInfo_OK(Integer id) {
 5         return "線程池:" + Thread.currentThread().getName()
 6                 + ",paymentInfo_OK,ID == " + id;
 7     }
 8 
 9 
10     // fallbackMethod: 設置HystrixCommand服務降級所使用的方法名稱,注意該方法需要與原方法定義在同一個類中,並且方法簽名也要一致
11     // commandProperties: 設置HystrixCommand屬性,如:斷路器失敗百分比、斷路器時間容器大小等
12     // 設置斷路器超時降級策略,時間3000毫秒超時
13     @HystrixCommand(fallbackMethod = "paymentInfo_TimeoutHandler", commandProperties = {
14             @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "3000")
15     })
16     public String paymentInfo_Timeout(Integer id) {
17         int second = 5000;
18         try {
19             // 休眠5000毫秒
20             TimeUnit.MILLISECONDS.sleep(second);
21         } catch (InterruptedException e) {
22             e.printStackTrace();
23         }
24         // 異常
25 //        int n = 10/0;
26         return "線程池:" + Thread.currentThread().getName()
27                 + ",paymentInfo_Timeout,ID == " + id
28                 + ",耗時" + second + "毫秒";
29     }
30 
31     public String paymentInfo_TimeoutHandler(Integer id) {
32         String result = "線程池:" + Thread.currentThread().getName()
33                 + ",paymentInfo_TimeoutHandler,ID == " + id;
34         return result;
35     }
36 }

  5、編輯controller

 1 @RestController
 2 @Slf4j
 3 public class PaymentController {
 4 
 5     @Autowired
 6     private PaymentService paymentService;
 7 
 8     @Value("${server.port}")
 9     private String serverPort;
10 
11     @GetMapping(value = "/payment/hystrix/ok/{id}")
12     public String paymentInfo_OK(@PathVariable("id") Integer id) {
13         String result = paymentService.paymentInfo_OK(id);
14         log.info("result===" + result);
15         return result;
16     }
17 
18     @GetMapping(value = "/payment/hystrix/timeout/{id}")
19     public String paymentInfo_Timeout(@PathVariable("id") Integer id) {
20         String result = paymentService.paymentInfo_Timeout(id);
21         log.info("result===" + result);
22         return result;
23     }
24 
25 }

  6、測試,啟動注冊中心,以及服務提供者項目

    訪問地址:http://localhost:8008/payment/hystrix/ok/1,正常響應

    

    訪問地址:http://localhost:8008/payment/hystrix/timeout/1,服務降級

    

    同時,可以修改業務類中paymentInfo_Timeout方法,讓此方法報異常,然后進行訪問,發現一樣會服務降級

全局服務降級DefaultProperties

  1、在服務消費者模塊(test-springcloud-order7996)中,引入Hystrix的依賴:

    完整pom如下:

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <project xmlns="http://maven.apache.org/POM/4.0.0"
 3          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 4          xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
 5     <parent>
 6         <artifactId>test-springcloud</artifactId>
 7         <groupId>com.test</groupId>
 8         <version>1.0-SNAPSHOT</version>
 9     </parent>
10     <modelVersion>4.0.0</modelVersion>
11 
12     <artifactId>test-springcloud-order7996</artifactId>
13 
14     <dependencies>
15 
16         <!-- hystrix -->
17         <dependency>
18             <groupId>org.springframework.cloud</groupId>
19             <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
20         </dependency>
21 
22         <!-- openfeign -->
23         <dependency>
24             <groupId>org.springframework.cloud</groupId>
25             <artifactId>spring-cloud-starter-openfeign</artifactId>
26         </dependency>
27 
28         <!-- eureka client -->
29         <dependency>
30             <groupId>org.springframework.cloud</groupId>
31             <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
32         </dependency>
33 
34         <!-- spring boot -->
35         <dependency>
36             <groupId>org.springframework.boot</groupId>
37             <artifactId>spring-boot-starter-web</artifactId>
38         </dependency>
39         <dependency>
40             <groupId>org.springframework.boot</groupId>
41             <artifactId>spring-boot-starter-actuator</artifactId>
42         </dependency>
43 
44         <dependency>
45             <groupId>org.springframework.boot</groupId>
46             <artifactId>spring-boot-devtools</artifactId>
47             <scope>runtime</scope>
48             <optional>true</optional>
49         </dependency>
50 
51         <dependency>
52             <groupId>org.projectlombok</groupId>
53             <artifactId>lombok</artifactId>
54             <optional>true</optional>
55         </dependency>
56         <dependency>
57             <groupId>org.springframework.boot</groupId>
58             <artifactId>spring-boot-starter-test</artifactId>
59             <scope>test</scope>
60         </dependency>
61 
62     </dependencies>
63 
64     <build>
65         <finalName>test-springcloud-order7996</finalName>
66     </build>
67 </project>
pom.xml

  2、編輯配置文件如下:

 1 # 端口
 2 server:
 3   port: 7996
 4 
 5 spring:
 6   application:
 7     name: cloud-order
 8 
 9 eureka:
10   client:
11     service-url:
12       defaultZone: http://localhost:8761/eureka
13   instance:
14     #  instance:
15     instance-id: ${spring.cloud.client.ip-address}:${server.port}
16     # 訪問路徑可以顯示IP地址
17     prefer-ip-address: true

  3、編輯啟動類

    使用注解@EnableFeignClients,啟動openfeign

    使用注解@EnableHystrix,啟用Hystrix,查看注解@EnableHystrix,里面也包含了注解@EnableCircuitBreaker

 1 @SpringBootApplication
 2 @EnableEurekaClient
 3 @EnableFeignClients
 4 // 啟動Hystrix
 5 @EnableHystrix
 6 public class OrderMain7996 {
 7     public static void main(String[] args) {
 8         SpringApplication.run(OrderMain7996.class, args);
 9     }
10 }

  4、編輯一個接口,並使用@FeignClient注解,表明一個是openfeign客戶端

 1 @Component
 2 // openfeign客戶端
 3 @FeignClient(value = "CLOUD-PAYMENT-SERVICE") 4 public interface PaymentHystrixService {
 5 
 6     @GetMapping(value = "/payment/hystrix/ok/{id}")
 7     public String paymentInfo_OK(@PathVariable("id") Integer id);
 8 
 9     @GetMapping(value = "/payment/hystrix/timeout/{id}")
10     public String paymentInfo_Timeout(@PathVariable("id") Integer id);
11 }

  5、編寫一個controller,內容如下

    1)類上需要使用@DefaultProperties(defaultFallback = "paymentClobalFallbackMethod"),定義一個默認的回調方法

    2)paymentTimeout方法上需要使用@HystrixCommand 支持服務降級

 1 @RestController
 2 @Slf4j
 3 @DefaultProperties(defaultFallback = "paymentClobalFallbackMethod")
 4 public class OrderHystrixController {
 5     @Autowired
 6     private PaymentHystrixService paymentHystrixService;
 7 
 8     @GetMapping(value = "/consumer/payment/hystrix/ok/{id}")
 9     public String paymentInfo_OK(@PathVariable("id") Integer id) {
10         String result = paymentHystrixService.paymentInfo_OK(id);
11         log.info("result===" + result);
12         return result;
13     }
14 //    @HystrixCommand(fallbackMethod = "paymentTimeoutFallbackMethod", commandProperties = {
15 //            @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "1500")
16 //    })
17     @GetMapping(value = "/consumer/payment/hystrix/timeout/{id}")
18     // @HystrixCommand 支持服務降級
19     @HystrixCommand
20     public String paymentTimeout(@PathVariable("id") Integer id) {
21         int n = 10/0;
22         String result = paymentHystrixService.paymentInfo_Timeout(id);
23         log.info("result===" + result);
24         return result;
25     }
26 
27     public String paymentTimeoutFallbackMethod(@PathVariable("id") Integer id) {
28         String result = "消費者:對方支付系統繁忙,請稍后再試,ID == " + id;
29         log.info("result===" + result);
30         return result;
31     }
32 
33

  6、測試

    1)啟動Eureka注冊中心,關閉服務提供者項目,啟動服務消費者模塊(test-springcloud-order7996)

    2)訪問地址:http://localhost:7996/consumer/payment/hystrix/ok/1,不支持服務降級

      

    3)訪問地址:http://localhost:7996/consumer/payment/hystrix/timeout/1,支持服務降級

      

通配服務降級

  1、在以上項目的基礎上,新增接口實現類PaymentFallbackService,實現接口PaymentHystrixService

 1 @Component
 2 public class PaymentFallbackService implements PaymentHystrixService {
 3     public String paymentInfo_OK(Integer id) {
 4         return "PaymentFallbackService——》paymentInfo_OK——》統一處理:" + id;
 5     }
 6 
 7     public String paymentInfo_Timeout(Integer id) {
 8         return "PaymentFallbackService——》paymentInfo_Timeout——》統一處理:" + id;
 9     }
10 }

  2、修改接口PaymentHystrixService的配置,如下:

1 @Component
2 // openfeign客戶端
3 // fallback: 定義容錯的處理類,當調用遠程接口失敗或超時時,會調用對應接口的容錯邏輯,
4 // fallback指定的類必須實現@FeignClient標記的接口
5 @FeignClient(value = "CLOUD-PAYMENT-SERVICE", fallback = PaymentFallbackService.class)
6 public interface PaymentHystrixService {

  3、測試

    1)啟動Eureka注冊中心,關閉服務提供者項目,啟動服務消費者模塊(test-springcloud-order7996)

    2)訪問地址:http://localhost:7996/consumer/payment/hystrix/ok/1,支持服務降級,且是通配服務降級的返回內容

      

    3)訪問地址:http://localhost:7996/consumer/payment/hystrix/timeout/1,支持服務降級,返回的是默認全局的服務降級內容

      

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM