TODO

  • 视频看到1.7,代码没跟了 ```properties 大概率的事件使用,极小的性能损耗完成

小概率事件,使用兜底方案

  1. <a name="Ea09e"></a>
  2. # 1. Hystrix的体系架构和核心功能
  3. <a name="cJa54"></a>
  4. ## 1.1 没有服务容错的一些场景
  5. <a name="FNjit"></a>
  6. ### 1.1.1 服务雪崩
  7. 服务雪崩:由最上游请求超时,导致所有链路全部崩溃
  8. <a name="J8Vxi"></a>
  9. ### 1.1.2 容器线程耗尽
  10. 容器线程耗尽:某个服务请求过于超时,缓慢积累会导致线程池内所有的线程都被该请求占用(使用容器级别的线程隔离技术)
  11. <a name="nv66F"></a>
  12. ## 1.2 服务容错的解决方案
  13. 如何降低服务故障影的影响
  14. 1. 隔离异常服务:线程隔离,给每个不同的请求分配指定的线程,系统不会应为某个请求超时,影响其它请求
  15. 1. 减压:快速失败(熔断),部分请求直接返回既定好的失败信息
  16. 1. 备选方案:服务降级,对于需要保障的请求,提供多种方案 ,降级的极致就是最小可用性
  17. <a name="tyr8x"></a>
  18. ### 1.2.1 服务降级![image.png](https://cdn.nlark.com/yuque/0/2022/png/26687455/1647149546735-16fd1029-8ea8-4fc7-995c-7d413a6247c6.png#clientId=u6c8c1170-adfd-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=305&id=u62b42006&margin=%5Bobject%20Object%5D&name=image.png&originHeight=610&originWidth=1246&originalType=binary&ratio=1&rotation=0&showTitle=false&size=121002&status=done&style=none&taskId=u9a37ce37-0425-4215-bd90-af36d981a1a&title=&width=623)
  19. <a name="Q6lCp"></a>
  20. ### 1.2.2 服务熔断
  21. ![image.png](https://cdn.nlark.com/yuque/0/2022/png/26687455/1647150480604-92e01bc9-4aa7-4676-945f-a6c3fc235653.png#clientId=u6c8c1170-adfd-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=300&id=u4549f880&margin=%5Bobject%20Object%5D&name=image.png&originHeight=600&originWidth=1326&originalType=binary&ratio=1&rotation=0&showTitle=false&size=133452&status=done&style=none&taskId=uf6649510-7310-480a-8489-81cd107fbfd&title=&width=663)
  22. 1. 熔断器是一个开关,Hystrix通过一些配置来判断是否开启还是关闭
  23. 1. 当开启的时候,服务请求不会直接去请求服务,而是直接请求FallBack
  24. 1. 熔断能有效解决QPS(Query Per Second,每秒访问请求,用来衡量当前系统压力)激增导致的系统雪崩效应
  25. <a name="nEI5m"></a>
  26. ### 1.2.2 线程隔离![image.png](https://cdn.nlark.com/yuque/0/2022/png/26687455/1647146432486-49616f52-39ce-4f3d-9058-c46f2af8119c.png#clientId=u6c8c1170-adfd-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=320&id=ue98a0993&margin=%5Bobject%20Object%5D&name=image.png&originHeight=640&originWidth=1336&originalType=binary&ratio=1&rotation=0&showTitle=false&size=164895&status=done&style=none&taskId=u04772901-29de-4d92-97f9-74c30a9b258&title=&width=668)
  27. <a name="wznte"></a>
  28. # 2. 服务降级
  29. <a name="la09J"></a>
  30. ## 2.1 降级的写法
  31. ```java
  32. @HystrixCommand(fallbackMethod = "putInPrison")
  33. public String bigTiger() {
  34. throw RuntimeException("Eat People");
  35. }
  36. // @HystrixCommand直接作用在需要降级的服务请求上,没有这个注解的则不需要服务将降级
  37. // fallbackMethod = "putInPrison":降级的处理流程,注意降级方法如果有参数也是需要写的
  38. // @HystrixCommand更多参数信息,查看RequestCatch解析
  1. @FeignClient(name = "feign-service-provider", fallback = Fallback.class)
  2. public interface MyHelloService extends HelloService {
  3. }
  4. // Fallback处理这个请求的降级流程:这里有没有@HystrixCommand表明这个接口里面的方法都需要走降级业务

2.2 降级的原理分析

2.2.1 原理分析

image.png

  1. @HystrixCommand:标识该注解,这个方法被Hystrix管理
  2. Aspect切面拦截
  3. RequestCatch:请求缓存,请求缓存的cel
    1. 如果处于开启状态,则尝试使用CatchKey从本地缓存中获取数据,也就不用发起方法调用了
    2. 如果关闭状态,则走下面的流程
  4. 注册Observer(观察者模式):方法正常执行、抛出异常、或者结束等状态,都有对应的回调函数
  5. 发起调用:在发起调用之前,会检查熔断状态,如果是开启的状态则直接fallback,否则发起调用
  6. 请求异常:异常则会触发第4步中注册的回调函数,然后直接转给fallback

    2.2.2 RequestCatch

  7. 该功能并不是让你在fallback的方法里面去访问缓存信息,而是Hystrix会将结果进行缓存

  8. 该功能是通过@CacheResult、@CacheKey两个注解完成的
  9. 在一个Hystrix上下文中,如果使用相同的参数对@CacheResult修饰的方法多次调用,Hystrix只会在首次向服务节点发送请求,而后续的请求则是读取第一次的缓存信息
  10. RequestCatch更像是一种性能优化(当然所有的缓存都是为了性能优化而生) ```java @Service public class service{

    @Autowired privite IService iservice;

    @CacheResult // @CacheResult:意思是该方法的结果可以被Hystrix缓存起来 @HystrixCommand(fallbackMethod = “putInPrison”, commandkey = “catchKey”) public Friend requestCache(@CacheKey Integer id) { // @CacheKey:指这个缓存的结果的业务id System.out.prinlt(“请求….”) } }

// commandkey = “catchKey”,中的catchKey可以替换方法级别的超时时间配置的key // hystrix.command.MyService#retry(Integer).execution.isolation.thread.timeoutInMilliseconds = 3000

// 必须是同一个类

// 如何开启上下文(说实话这个开启就是只能在一个请求中,如果这个请求能操作两次数据,可以使用到缓存,比较鸡肋,想要多次使用,需要扩大范围) HystrixRequestContext context = HystrixRequestContext.initializeContext();

  1. ```properties
  2. ## 是否开启缓存(默认打开的,无需配置)
  3. hystrix.command.default.requestCatch.enabled = true

2.3 降级的常用方案

参考文章:https://class.imooc.com/lesson/1241#mid=29759

2.3.1 静默处理

image.png

2.3.2 默认值

  • 主链路容忍性差

image.png

2.3.3 想办法恢复服务

(1) 缓存异常

  • 假如因为缓存故障无法访问数据,在fallback中的逻辑中可以转而访问底层数据库(这个方法不可以使用在热点数据上,否则可能把数据库打挂,或者引起更大的降级或者熔断,谨慎使用)
  • 但是可以反过来,数据库挂了,可以先访问缓存,但是注意数据一致性

    (2) 切换备库

  • 一般大型系统都会做主从+备库的方式做灾备,假如主数据库发生了故障,切换到备用数据库。

  • 这个场景尽量使用在核心线路上,避免造成脏读或者幻读

    (3) 重试

  • ribbon可以处理超时重试,但对于异常情况来说(比如当前资源被锁定),可以在fallback中自己尝试重新发起接口调用

    (4) 人工干预

  • 对于机器重要的接口,对异常不能容忍,这里可以借用fallback启动人工干预流程

  • 比如日志打点,通过监控组件触发报警,人工干预

    2.3.4 多次降级

    image.png

    2.4 代码实战

    2.4.1 简单的降级配置

    异常降级、超时降级(超时配置看下面)

    (1) 基础配置

    ```properties

    开启fegin下面的hystrix功能(默认开启的,不用配置)

    feign.hystrix.enable = true

是否开启服务降级(默认开启的,不用配置)

hystrix.command.default.fallback.enable = true

  1. <a name="qrBE1"></a>
  2. #### (2) 超时配置
  3. ```properties
  4. ## 开启全局超时配置
  5. hystrix.command.default.execution.timeout.enable = true
  6. ## 设置超时时间(毫秒),设置超时时间为两秒,注意等于设置的时间也算超时
  7. hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds = 2000
  8. ## 超时以后线程终止
  9. hystrix.command.default.execution.isolation.thread.interruptOnTimeout = true
  10. ## 取消的时候线程终止
  11. hystrix.command.default.execution.isolation.thread.interruptOnFutureCancel = true
  12. ## 思考?feign和hystrix都设置重试时间如何处理?下面的设置是feign的时间远大于hystrix,具体配置信息查看feign章节
  13. feign-service-provider.ribbon.OkToRetryOnAllOperations = false
  14. feign-service-provider.ribbon.ConnectTimeout = 1000
  15. feign-service-provider.ribbon.ReadTimeout = 8000
  16. feign-service-provider.ribbon.MaxAutoRetries = 0
  17. feign-service-provider.ribbon.MaxAutoRetriesNextServer = 0
  18. ## 为方法级别的设置超时时间,这个配置会覆盖全局配置-------------------
  19. ## default换成具体的方法信息:类名#方法名称(变量类型)
  20. hystrix.command.MyService#retry(Integer).execution.isolation.thread.timeoutInMilliseconds = 3000
  21. ## 有个函数可以自动生成这个替换信息,是通过反射的方式
  22. Feign.configKey(类名.class, 类名.class.getMethod("方法名称",参数类型.class))
  23. feign.configKey(MyService.class, MyService.class.getMethod("retry",int.class))
  24. ## 通过commandKey配置,查看requestCatch章节
  25. ## 注解配置看下面图片

image.png

2.4.2 多级降级

一直降级还是不能解决,直接熔断
@HystrixCommand(fallbackmethod = “”),直接指定就行了

2.5 Hystrix和Ribbon超时冲突

强制开启熔断开关(默认 = false),如果打开了,所有正常调用的服务也会开启熔断

hystrix.command.default.circuitBreaker.forceOpen = false

强制关闭熔断开关(默认 = false)

hystrix.command.default.circuitBreaker.forceClosed = false

  1. ```properties
  2. ## 窗口时间,根据设置的值来统计这个时间内异常请求,默认值是毫秒级别,默认值是5000
  3. ## 示例配置的含义是:以每隔20秒的窗口来统计异常请求数量
  4. hystrix.command.default.metrics.rollingStats.timeInMilliseconds = 20000
  5. ## 熔断的前提条件(指请求的数量)
  6. ## 示例配置的含义是:在一定的时间窗口内,请求达到5个以后,才开始进行熔断判断
  7. hystrix.command.default.circuitBreaker.requestVolumeThreshold = 5
  8. ## 熔断的前提条件(指异常请求在所有请求中的占比)
  9. ## 示例配置的含义是:在一定的时间窗口内,异常请求达到50%,才开始进行熔断判断
  10. hystrix.command.default.circuitBreaker.errorThresholdPercentage = 50
  11. ## 当熔断开启之后,经过多少秒进入半开状态(这个时间一般要小于窗口时间)
  12. hystrix.command.default.circuitBreaker.sleepWindowInMilliseconds = 10000

4. 线程隔离

https://class.imooc.com/lesson/1241#mid=30013
https://class.imooc.com/lesson/1241#mid=30014

5. turbine聚合hystrix信息

参考文章:https://class.imooc.com/lesson/1241#mid=30015