一、概念

1、什么是服务降级

有了服务的熔断,随之就会有服务的降级,所谓服务降级,就是当某个服务熔断之后,服务端提供的服务将不再被调用,此时由客户端自己准备一个本地的fallback回调,返回一个默认值来代表服务端的返回; 这种做法,虽然不能得到正确的返回结果,但至少保证了服务的可用,比直接抛出错误或者服务不可用要好很多。

二、如何进行服务降级

(1) 服务端

1、POM

  1. <dependencies>
  2. <!--hystrix-->
  3. <dependency>
  4. <groupId>org.springframework.cloud</groupId>
  5. <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
  6. </dependency>
  7. <!--eureka client-->
  8. <dependency>
  9. <groupId>org.springframework.cloud</groupId>
  10. <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
  11. </dependency>
  12. <!--web-->
  13. <dependency>
  14. <groupId>org.springframework.boot</groupId>
  15. <artifactId>spring-boot-starter-web</artifactId>
  16. </dependency>
  17. <dependency>
  18. <groupId>org.springframework.boot</groupId>
  19. <artifactId>spring-boot-starter-actuator</artifactId>
  20. </dependency>
  21. <dependency>
  22. <groupId>com.tfjy.springcloud</groupId>
  23. <artifactId>cloud-api-commons</artifactId>
  24. <version>1.0-SNAPSHOT</version>
  25. </dependency>
  26. <dependency>
  27. <groupId>org.springframework.boot</groupId>
  28. <artifactId>spring-boot-devtools</artifactId>
  29. <scope>runtime</scope>
  30. <optional>true</optional>
  31. </dependency>
  32. <dependency>
  33. <groupId>org.projectlombok</groupId>
  34. <artifactId>lombok</artifactId>
  35. <optional>true</optional>
  36. </dependency>
  37. <dependency>
  38. <groupId>org.springframework.boot</groupId>
  39. <artifactId>spring-boot-starter-test</artifactId>
  40. <scope>test</scope>
  41. </dependency>
  42. </dependencies>

2、YML

  1. server:
  2. port: 8001
  3. spring:
  4. application:
  5. name: cloud-provider-hystrix-payment
  6. eureka:
  7. client:
  8. register-with-eureka: true
  9. fetch-registry: true
  10. service-url:
  11. #defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka
  12. defaultZone: http://localhost:7001/eureka/

3、主启动

需要在主启动上加上
image.png

4、业务类

controller

  1. @GetMapping("/payment/hystrix/timeout/{id}")
  2. public String paymentInfo_TimeOut(@PathVariable("id") Integer id){
  3. String result = paymentService.paymentInfo_TimeOut(id);
  4. log.info("*****result"+result);
  5. return result;
  6. }

service

  1. @HystrixCommand(fallbackMethod = "paymentInfo_TimeOutHandler",commandProperties = {
  2. @HystrixProperty(name="execution.isolation.thread.timeoutInMilliseconds",value="5000")
  3. })
  4. public String paymentInfo_TimeOut(Integer id){
  5. try{
  6. TimeUnit.SECONDS.sleep(5);
  7. }catch (InterruptedException e){
  8. e.printStackTrace();
  9. }
  10. return "线程池:"+Thread.currentThread().getName()+"paymentInfo_TimeOut,id"+id+"O(∩_∩)O哈哈~"+"耗时5秒钟";
  11. }
  12. public String paymentInfo_TimeOutHandler(Integer id){
  13. return "线程池:"+Thread.currentThread().getName()+"paymentInfo_TimeOutHandler,id"+id+"o(╥﹏╥)o";
  14. }

在代码上加上HystrixCommand注解,然后由个属性fallbackMethod,value值可以填写方法的名字。
当发生超时的时候,就会走下面的方法。

(2)客户端

服务降级 - 图2

1、POM

  1. <dependencies>
  2. <!--openfeign-->
  3. <dependency>
  4. <groupId>org.springframework.cloud</groupId>
  5. <artifactId>spring-cloud-starter-openfeign</artifactId>
  6. </dependency>
  7. <!--hystrix-->
  8. <dependency>
  9. <groupId>org.springframework.cloud</groupId>
  10. <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
  11. </dependency>
  12. <!--eureka client-->
  13. <dependency>
  14. <groupId>org.springframework.cloud</groupId>
  15. <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
  16. </dependency>
  17. <!-- 引入自己定义的api通用包,可以使用Payment支付Entity -->
  18. <dependency>
  19. <groupId>com.tfjy.springcloud</groupId>
  20. <artifactId>cloud-api-commons</artifactId>
  21. <version>1.0-SNAPSHOT</version>
  22. </dependency>
  23. <!--web-->
  24. <dependency>
  25. <groupId>org.springframework.boot</groupId>
  26. <artifactId>spring-boot-starter-web</artifactId>
  27. </dependency>
  28. <dependency>
  29. <groupId>org.springframework.boot</groupId>
  30. <artifactId>spring-boot-starter-actuator</artifactId>
  31. </dependency>
  32. <!--一般基础通用配置-->
  33. <dependency>
  34. <groupId>org.springframework.boot</groupId>
  35. <artifactId>spring-boot-devtools</artifactId>
  36. <scope>runtime</scope>
  37. <optional>true</optional>
  38. </dependency>
  39. <dependency>
  40. <groupId>org.projectlombok</groupId>
  41. <artifactId>lombok</artifactId>
  42. <optional>true</optional>
  43. </dependency>
  44. <dependency>
  45. <groupId>org.springframework.boot</groupId>
  46. <artifactId>spring-boot-starter-test</artifactId>
  47. <scope>test</scope>
  48. </dependency>
  49. </dependencies>

2、YML

  1. server:
  2. port: 80
  3. eureka:
  4. client:
  5. register-with-eureka: false
  6. service-url:
  7. defaultZone: http://localhost:7001/eureka/
  8. feign:
  9. hystrix:
  10. enabled: true

3、主启动

image.png

4、业务

  1. @GetMapping("/consumer/payment/hystrix/timeout/{id}")
  2. @HystrixCommand(fallbackMethod = "paymentTimeOutFallbackMethod",commandProperties = {
  3. @HystrixProperty(name="execution.isolation.thread.timeoutInMilliseconds",value="1500")
  4. })
  5. // @HystrixCommand
  6. public String paymentInfo_TimeOut(@PathVariable("id") Integer id)
  7. {
  8. int age = 10/0;
  9. String result = paymentHystrixService.paymentInfo_TimeOut(id);
  10. return result;
  11. }
  12. public String paymentTimeOutFallbackMethod(@PathVariable("id") Integer id)
  13. {
  14. return "我是消费者80,对方支付系统繁忙请10秒钟后再试或者自己运行出错请检查自己,o(╥﹏╥)o";
  15. }
  1. @Component
  2. @FeignClient(value = "CLOUD-PROVIDER-HYSTRIX-PAYMENT",fallback = PaymentFallbackService.class)
  3. public interface PaymentHystrixService {
  4. @GetMapping("/payment/hystrix/ok/{id}")
  5. public String paymentInfo_ok(@PathVariable("id") Integer id);
  6. @GetMapping("/payment/hystrix/timeout/{id}")
  7. public String paymentInfo_TimeOut(@PathVariable("id") Integer id);
  8. }

这个参数要一样

这个只能等待1.5s但是在8001要5s
image.png

三、全局配置

  1. @RestController
  2. @Slf4j
  3. @DefaultProperties(defaultFallback = "payment_Global_FallbackMethod")
  4. public class OrderHystirxController {
  5. @GetMapping("/consumer/payment/hystrix/timeout/{id}")
  6. // @HystrixCommand(fallbackMethod = "paymentTimeOutFallbackMethod",commandProperties = {
  7. // @HystrixProperty(name="execution.isolation.thread.timeoutInMilliseconds",value="1500")
  8. // })
  9. @HystrixCommand
  10. public String paymentInfo_TimeOut(@PathVariable("id") Integer id)
  11. {
  12. int age = 10/0;
  13. String result = paymentHystrixService.paymentInfo_TimeOut(id);
  14. return result;
  15. }
  16. public String paymentTimeOutFallbackMethod(@PathVariable("id") Integer id)
  17. {
  18. return "我是消费者80,对方支付系统繁忙请10秒钟后再试或者自己运行出错请检查自己,o(╥﹏╥)o";
  19. }
  20. // 下面是全局fallback方法
  21. public String payment_Global_FallbackMethod()
  22. {
  23. return "Global异常处理信息,请稍后再试,/(ㄒoㄒ)/~~";
  24. }
  25. }

@DefaultProperties(defaultFallback = “payment_Global_FallbackMethod”)

1:1 每个方法配置一个服务降级方法,技术上可以,实际上傻X
1:N 除了个别重要核心业务有专属,其它普通的可以通过@DefaultProperties(defaultFallback = “”) 统一跳转到统一处理结果页面

通用和独享的各自分开,避免了代码膨胀,合理减少了代码量
image.png

三、哪些情况会发生服务降级

(1) 程序运行异常 (当我们把service方法中改成int i =10/0)
(2) 超时
(3) 服务熔断触发服务降级
(4) 线程池/信号量也会导致服务降级