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

          

  • 相关阅读:
    [51NOD]大数加法(模拟)
    LCS记录路径
    BISTU-(1)-4-17-2016
    [CF580B]Kefa and Company(滑动窗口)
    [CF660C]Hard Process(尺取法)
    [POJ3061]Subsequence(二分,前缀和)
    [HDOJ2602]Bone Collector(01背包)
    [HDOJ1171]Big Event in HDU(01背包)
    [HDOJ2512]一卡通大冒险(DP)
    hdu 1269 迷宫城堡 最简单的联通图题 kosaraju缩点算法
  • 原文地址:https://www.cnblogs.com/h--d/p/12702011.html
Copyright © 2011-2022 走看看