zoukankan      html  css  js  c++  java
  • 【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,支持服务降级,返回的是默认全局的服务降级内容

          

  • 相关阅读:
    Postgresql HStore 插件试用小结
    postgres-xl 安装与部署 【异常处理】ERROR: could not open file (null)/STDIN_***_0 for write, No such file or directory
    GPDB 5.x PSQL Quick Reference
    postgresql 数据库schema 复制
    hive 打印日志
    gp与 pg 查询进程
    jquery table 发送两次请求 解惑
    python 字符串拼接效率打脸帖
    postgresql 日期类型处理实践
    IBM Rational Rose软件下载以及全破解方法
  • 原文地址:https://www.cnblogs.com/h--d/p/12702011.html
Copyright © 2011-2022 走看看