H__D  

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,支持服务降级,返回的是默认全局的服务降级内容

      

 

posted on 2020-04-14 22:57  H__D  阅读(1295)  评论(1编辑  收藏  举报