springcloud 系列 -- 简单了解一下 hystrix

写在前面

思考的过程往往比直接得到结论更加重要

1、为什么需要熔断器
服务雪崩

在分布式环境下,不可避免的就是服务之间的调用。A 调 B,B 可能会失败,如果此时 B 服务挂掉,那么会导致服务 A 因为服务 B 的失败而失败。从而导致 客户端认为 A 也是失败的。 简单说就是,牵一发而动全身

这也是,我们需要熔断器的原因。我们需要有保护服务调用的组件。当服务 B 挂掉时,服务 B 需要能够快速失败。

2、如果自己写一个断路器,你会怎么做呢?
隔离策略

思考一下,什么是隔离?
我对他的理解,大概就是,服务 A 调用服务 B,服务 C。不能因为调用服务 B 出现问题,而导致调用服务 C 也出现问题。也就是,服务B、服务C 的调用应该放在不同的环境下。

常见的资源隔离,有线程池隔离,信号量隔离

线程池隔离信号量隔离
线程请求线程和调用 provider 不是同一个线程请求线程和调用 provider 是同一个线程
开销排队、调度、上下文开销等无线程切换,开销低
异步支持不支持
并发支持支持(线程池大小)支持(信号量上限)
传递 Header无法传递 Http Header可以传递 Http Header
快速失败

当 provider 提供的服务不可用,或出现异常时,应该有可供回调的降级方法。

  • provider 调用失败抛出异常,可能针对某种异常,不想执行快速失败策略,而是需要直接抛出异常
  • provider 调用失败,可能不想执行快速失败策略,也不想抛出任何异常。
限流

当 provider 被大量调用时,为了保护链路,需要做限流。那么其实核心的问题是,如何进行统计。

统计

每个 provider 的调用情况需要统计。这样可以更好的监控到 provider 提供的服务的情况。统计的算法,应该是基于滑动窗口进行统计。

熔断

因为有对每个 provider 调用情况统计,在调用之前,失败次数达到某个阈值时,可以认为该 provider 已经是有问题的,可以直接快速失败,以防止服务雪崩情况。

系统自适应保护

熔断机制是针对每个 provider 的。但是,有可能服务系统已经要达到极限了,不能再接收任何请求了,那么此时,出于系统的保护,也应该快速失败。

扩展

作为一个组件,支持扩展那是必须。
常见的扩展方式:(其实就是面向接口编程,在某些执行流程中,暴露出部分接口。剩下的就看你怎么封装了)

  • 观察者设计模式 + 策略设计模式。 例如
public interface SayListener {
  String say();
}

public class App {
    List<SayListener> sayListener = new ArrayList<>();
    public void doSomething() {
      // ...
       
      sayAction();
       // 触发了 say 的动作
      if (null != sayListener && sayListener.size() > 0) {
          sayListener.forEach(listener -> {
            listener.say();
          });
      }
       
       
      // ...
    }
    
    public void sayAction() {}
    
    public void registerSayListener(SayListener listener) {
       sayListener.add(listener);
    }
}

3、现有类似功能组件对比
sentinelhystrixresilience4j
隔离策略信号量隔离(并发线程数限流)线程池隔离/信号量隔离信号量隔离
熔断降级策略基于响应时间、异常比率、异常数基于异常比率基于异常比率、响应时间
实时统计实现滑动窗口(LeapArray)滑动窗口(RxJava)Ring Bit Buffer
动态规则配置支持多种数据源支持多种数据源有限支持
扩展性多个扩展点插件形式接口形式
基于注解的支持支持支持支持
限流基于 QPS, 支持基于调用关系的限流基于线程池个数有限支持Rate Limiter
系统自适应保护支持不支持不支持
控制台丰富简单不提供控制台,可对接其他监控系统

hystrix wiki 介绍实在太全了,这里就没必要在介绍了,主要是从个人的角度去思考如果让自己也实现一个断路器中间件,你会怎么做?(鉴于 hystrix 停止维护,以及 sentinel 的活跃,重心会放在 sentinel 上)

4、使用注意

在使用 hystrix 需要注意的几个地方。

hystrix 超时设置

设置 hystrix 超时时间时,需要大于等于 ribbon 的超时时间。 例如 ribbon 的配置如下

ReadTimeout=1000 
ConnectTimeout=1000
MaxAutoRetries=1
MaxAutoRetriesNextServer=1

那么 hystrix 的超时时间公式为:

execution.isolation.thread.timeoutInMilliseconds >= (MaxAutoRetriesNextServer + 1) * (MaxAutoRetries + 1) * (ReadTimeout + ConnectTimeout)
hystrix 使用线程池隔离时,无法传递绑定在 tomcat 线程上下文的值

因为使用线程池隔离时(execution.isolation.strategy=THREAD),会新创建一个线程,因此 tomcat 线程的变量则无法传递给新的线程。那么此时可以使用 信号量隔离(execution.isolation.strategy=SEMAPHORE)。因为使用信号量隔离时,会使用 tomcat 线程调用远程服务。
其实 hystrix 也想到了会有这样的需求, 因此在 wiki 中,推荐我们继承 HystrixConcurrencyStrategy,重写 wrapCallable() 方法。 具体代码参考 线程池隔离传递 ThreadLocal 值
该作者是基于 spi 实现的(牛逼),其实 hystrix 提供了可配置的参数供我们配置

hystrix:
  plugin:
    HystrixConcurrencyStrategy:
      implementation: com.csp.hystrix.MyHystrixConcurrencyStrategy
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值