zoukankan      html  css  js  c++  java
  • SpringCloud(三)之我学 Hystrix

    1、断路器

      在消费服务的启动类,添加注解:@EnableCircuitBreaker,在消费服务的调用类上,添加注解:@HystrixCommand(fallbackMethod = "") -> 失败了调的方法。(熔断超时默认 2s )

      当被调用的服务,超时或者未反应/down掉,就会触发熔断请求,返回定义的逻辑。

      工作流程:

      1)、加注解:@HystrixCommand 或 @HystrixObservableCommand ,前者用于依赖的服务返回单个操作结果的时候,后者用于依赖的服务返回多个操作结果的时候。(具体的实现看书籍)

      命令模式,将客户端请求封装为一个对象,能让不同的请求对客户端进行参数化。(让不同类型的参数,都可以请求)

      2)、命令执行:

      HystrixCommand 实现了 execute()、queue() 执行方法。

      execute():同步执行,从依赖的服务返回一个单一的结果对象,或错误时抛出异常,R value = command.execute();

      queue():异步执行,直接返回一个 Future 对象,其中包含了服务执行结束时返回的单一结果对象,Future<R> fValue = command.queue();

      HystrixObservableCommand 实现了 observe()、toObservable() 执行方法。

      Observable<R> obValue = command.observe(),代表操作了多个结果,返回 HotObservanle;

      Observable<R> ocValue = command.toObservable(),也代表操作了多个结果,返回 Cold Observable;

      Hystrix 底层实现了大量的 RxJava,RxJava 的观察者-订阅者模式。

      Observable 向订阅者 Subscriber 对象发布事件(即异服务调用),一个Observable 可以发出多个事件,直到结束或者发生异常。每发出一个事件,就会调用对应观察者 Subscriber.onNext() 方法。最后一定会调用 Subscriber.onCompleted() 或者 Subscriber.onError() 结束该时间的操作流。

      3)、结果是否被缓存:当命令的请求缓存功能开启,命令缓存命中,缓存的结果就会以 Observable 对象的形式返回。

      4)、断路器是否打开: - 断路器是否已经开始运行

      命令结果没有命中缓存中,如果断路器打开,Hystrix 不会执行命令,而是转到 fallback 处理逻辑。如果断路器关闭,则继续执行。

      5)、线程池/请求队列/信号量是否占满: - 线程太多

      如果与命令相关的线程池或请求队列或者信号量已经占满,则 Hystrix 也不会执行命令,而是转接到 fallback 处理逻辑。

      该线程池并非容易的线程池,而是每个依赖服务的专有线程池。

      6)、请求依赖服务:

      HystrixObserveableCommand.construct() 或 HystrixCommand.run(),决定了采取什么样的方式去请求依赖服务。

      第一种返回一个 Observable 对象来发射多个结果,或通过 onError 发送错误通知;

      第二种返回一个单一的结果,或者抛出异常。

      超时也会转到 fallback 处理逻辑。

      7)、计算断路器的健康度: - 服务调用失败/超时等超过设置

      Hystrix 会将成功、失败、拒绝、超时等信息报告给断路器,断路器会维护一组计数器来统计这些数据。根据数据值,来对某个依赖服务的请求进行 "熔断/短路",直到恢复期结束。在恢复期结束后,再根据统计数据判断是否还是未达到健康指标,或再次"熔断/短路"。

      8)、fallback 处理:- 回退 - 服务降级

      当命令执行失败的时候,Hystrix 会进入 fallback 尝试回退处理,该操作叫做 "服务降级"。

      第4、5、6步都可能会引起服务降级。

      最终的降级逻辑一定不是一个依赖网络请求的处理,而是一个能够稳定返回结果的处理逻辑。

      HystrixCommand.getFallback() 来实现服务降级;

      HystrixObservableCommand.resumeWithFallback() 来实现降级逻辑。

      9)、返回成功的响应:

    2、断路器原理

      HystrixCricuitBreaker 接口:

      allowRequest:每个 hystrix 命令的请求都通过它判断是否被执行;

      isOpen:返回当前断路器是否打开;

      markSuccess():用来闭合断路器,并重置度量指标对象。

      HystrixCricuitBreakImpl 是实现类,有几个重要核心对象,一个是 HystrixCommand 实例的属性对象,一个是记录各个度量指标的对象,一个是断路器是否打开的标志,一个是断路器打开或上一次测试的时间戳。

      断路器从关闭到打开(默认时间窗10s的请求信息快照):

      1)、请求总数 QPS 在预设的阈值范围内就返回 false,表示断路器还是关闭。阈值默认值20。

      2)、错误百分比在阈值范围内就返回 false,表示断路器还是关闭。默认是50。

      3)、以上两个条件都不满足,断路器就设置为打开状态(熔断/短路)。如果是从关闭状态切到打开状态,就将当前时间记录到上面的时间戳对象中。

      allowSingleTest() 为断路器再设置一个休眠时间(默认5s),在该休眠时间达到只有,再次允许请求尝试访问。若请求再次失败,断路器又进入打开状态。请求成功,则是关闭状态。

      所以 allowSingleTest() 与 isOpen() 方法的配合,实现了断路器的打开和关闭状态的切换。

    3、依赖隔离

      会为每个依赖服务创建一个独立的线程池,这样就算某个依赖服务出现问题后,也只对该依赖服务的调用产生影响,不影响其他依赖服务。

      特点:

      依赖的服务从失效恢复正常后,它的线程池会被清理并且能够马上恢复健康服务。容器级别的清理 恢复速度慢的多;

      当依赖的服务出现配置错误的时候,线程池会被快速反映出此问题(失败、延迟、超时、拒绝等增加情况)。

      线程池的开销在设计的时候做过实验,消耗相对于来说是微乎其微的。对于某些需求来说,如果该消耗觉得很大,又用了信号量来优化。

      信号量控制单个依赖服务的并发量,但是不能设置超时和实现异步访问。线程池和信号量可以切换。

      在降级逻辑,Hystrix 尝试降级逻辑时,会在调用线程中使用信号量。或者命令执行。

    4、使用详解

      1)、创建请求命令

      可以用继承 HystrixCommand 或者 @HystrixCommand 来实现熔断,注解添加在异服务之间调用的接口上。

      并且该注解可以实现 同步/异步 的操作。异步用 Future<T> 接收返回参数。

      2)、定义服务降级

      fallback 是 Hystrix 命令执行失败后使用的后备办法,实现服务的降级处理逻辑。

      继承方式的话,用重载 getFallback() 方法来实现降级处理;

      注解方式 @HystrixCommand(fallbackMethod = "failMethod") ,定义一个 faliMethod 方法,作为降级处理。(在同一个类中)

      3)、异常处理

      当服务调用发生异常,除了 HystrixBadRequestException 之外,其他异常都会被 Hystrix 认为命令执行失败,并触发服务降级的处理逻辑。

      使用注解 @HystrixCommand(ignoreExceptions = {XXException.class}) 可以忽略指定异常类型。当遇到该类型的异常时,就会被包装 HystrixBadRequestException 异常抛出,而不会触发降级的处理逻辑。

      4)、异常获取

      异常获取到后,可以根据不同的异常判断,做出不同的处理方式。直接在 fallback() 方法里定义一个 Throwable e ,就可以获取触发降级的具体异常内容。(e.getMessage())

      5)、命令名称、分组以及线程池划分

      Hystrix 会让相同组名的命令使用同一个线程池。所以创建 Hystrix 命令时,为其制定命令组名来实现默认的线程池划分。(还提供了 HystrixThreadPoolKey 来对线程池进行设置,进行更加细粒度的线程池划分,实际情况通常使用这一种划分方式)

      注解方式实现:@HystrixCommand(commandKey="getUserById",groupKey="UserGroup",ThreadPoolKey="getUserByIdThread")

      6)、请求缓存

      开启请求缓存功能:继承方式,重载 getCacheKey() 方式来开启请求缓存。

      好处:

      减少重复请求数,降低依赖服务的并发度(降低压力);

      在同一用户请求的上下文中,相同依赖服务的返回数据一致;

      请求缓存在 run() 和 construct() 执行之前生效,可以减少不必要的线程开销;

      清理失效缓存功能:通过 HystrixRequestCache.clear() 方法来进行缓存的清理,在做更新操作时,就将缓存清理掉。

      注解方式:@CacheResult 标记请求命令返回的结果应该被缓存,必须和 @HystrixCommand 结合使用;

      @CacheRemove 让请求命令的缓存失效,失效的缓存是根据 key 来的。(commandKey)

      @CacheKey 给参数添加标记,使之成为缓存的 key。

      7)、请求合并

      远程调用最常见的问题就是 通信消耗和连接总数。Hystrix 提供了 HystrixCollapser 来实现请求的合并,以减少通信消耗和线程池的占用。

      HystrixCollapser 实现了 在 @HystrixCommand 之前放置了一个合并处理器,将处于一个很短时间内(默认10ms)对同一依赖服务的多个请求进行整合并以批量方式发起请求。

  • 相关阅读:
    XRP共识算法
    瑞波币交易
    Bitcoin区块验证
    Bitcoin挖矿
    Bitcoin区块链攻击方式
    Bitcoin交易及验证
    C# 《编写高质量代码改善建议》整理&笔记 --(五)类型设计
    C# 《编写高质量代码改善建议》整理&笔记 --(五)成员设计
    C# 《编写高质量代码改善建议》整理&笔记 --(四)资源管理&序列化
    C# 《编写高质量代码改善建议》整理&笔记 --(三)泛型&委托&事件
  • 原文地址:https://www.cnblogs.com/AlmostWasteTime/p/11213914.html
Copyright © 2011-2022 走看看