Hystrix学习笔记一

来源:互联网 发布:电商美工培训 编辑:程序博客网 时间:2024/06/05 11:18

在分布式系统中,通常一个系统会依赖很多个系统,如何保证自身系统不受依赖的系统的影响,导致连锁反应全面崩溃是一个重要的技术难题。所幸 Netflix 开源的 Hystrix框架 帮我们大大简化了超时机制和断路器的实现。

一般情况对于服务依赖的保护主要有3种解决方案:

(1)熔断模式:这种模式主要是参考电路熔断,如果一条线路电压过高,保险丝会熔断,防止火灾。放到我们的系统中,如果某个目标服务调用慢或者有大量超时,此时,熔断该服务的调用,对于后续调用请求,不在继续调用目标服务,直接返回,快速释放资源。如果目标服务情况好转则恢复调用。

(2)隔离模式:这种模式就像对系统请求按类型划分成一个个小岛的一样,当某个小岛被火烧光了,不会影响到其他的小岛。例如可以对不同类型的请求使用线程池来资源隔离,每种类型的请求互不影响,如果一种类型的请求线程资源耗尽,则对后续的该类型请求直接返回,不再调用后续资源。这种模式使用场景非常多,例如将一个服务拆开,对于重要的服务使用单独服务器来部署,再或者公司最近推广的多中心。

(3)限流模式:上述的熔断模式和隔离模式都属于出错后的容错处理机制,而限流模式则可以称为预防模式。限流模式主要是提前对各个类型的请求设置最高的QPS阈值,若高于设置的阈值则对该请求直接返回,不再调用后续资源。这种模式不能解决服务依赖的问题,只能解决系统整体资源分配问题,因为没有被限流的请求依然有可能造成雪崩效应。

熔断设计

在熔断的设计主要参考了hystrix的做法。其中最重要的是三个模块:熔断请求判断算法、熔断恢复机制、熔断报警

(1)熔断请求判断机制算法:使用无锁循环队列计数,每个熔断器默认维护10个bucket,每1秒一个bucket,每个blucket记录请求的成功、失败、超时、拒绝的状态,默认错误超过50%且10秒内超过20个请求进行中断拦截。

(2)熔断恢复:对于被熔断的请求,每隔5s允许部分请求通过,若请求都是健康的(RT<250ms)则对请求健康恢复。

(3)熔断报警:对于熔断的请求打日志,异常请求超过某些设定则报警

隔离设计

隔离的方式一般使用两种:

(1)线程池隔离模式:使用一个线程池来存储当前的请求,线程池对请求作处理,设置任务返回处理超时时间,堆积的请求堆积入线程池队列。这种方式需要为每个依赖的服务申请线程池,有一定的资源消耗,好处是可以应对突发流量(流量洪峰来临时,处理不完可将数据存储到线程池队里慢慢处理)。

(2)信号量隔离模式:使用一个原子计数器(或信号量)来记录当前有多少个线程在运行,请求来先判断计数器的数值,若超过设置的最大线程个数则丢弃改类型的新请求,若不超过则执行计数操作请求来计数器+1,请求返回计数器-1。这种方式是严格的控制线程且立即返回模式,无法应对突发流量(流量洪峰来临时,处理的线程超过数量,其他的请求会直接返回,不继续去请求依赖的服务)。



Hystrix是什么?

  • 官方地址:https://github.com/Netflix/Hystrix
  • Hystrix是由Netflix开源的一个服务隔离组件,通过服务隔离来避免由于依赖延迟、异常,引起资源耗尽导致系统不可用的解决方案。

我们是如何对依赖的服务进行容错的呢?

  • 大部分服务共用同一个线程池,在一定并发量的情况下,依赖的接口超时耗尽线程资源,影响其他服务导致系统不可用;
  • 对于可预见的雪崩,有经验的程序员提前加开关降级服务,没经验的只能哭着加开关走发布流程。
  • 归根到底,我们的系统在面对外部系统延迟、错误时,缺乏自动化、半自动化的降级、恢复机制。

Hystrix如何对依赖的服务进行容错的呢?

  • 隔离服务,统计运行指标,发现异常,自动降级,试探性恢复;
  • 提供信号量、线程池两种手段限制服务可用资源、统计服务运行成功、失败、超时等计数;
  • 熔断(开路)服务;
  • 时间窗口试探性恢复服务。

Hystrix有哪些值得借鉴的实现细节?

  • 整个Hystrix都值得细细分析,例如它通过React提升系统吞吐量,炫酷的dashborad,运行指标无锁统计等等。
  • 如果要自己动手实现一套容错系统,我觉得有几件事是要首先被关注的(1)异常的判断依据(指标)、(2)可以实施的办法(策略)、(3)办法实施的时机。当然,这些内容在Hystrix的官方文档上都有比较详细的介绍,下面我想简单记录下,在这三件事背后,Hystrix是如何高效无锁的统计指标的。

HystrixRollingNumber

  • 在统计指标项时,如果每个周期都从零开始统计,那么会得到一个周期性出现锯齿的统计曲线,在系统层面上会表现为对依赖的服务造成herd effect。
  • 因此,Hystrix将一个统计周期分解为更小的段(bucket),通过移动时间窗口淘汰最老的bucket。

  • 每当需要开始一个新的bucket时,牺牲可容忍的准确性,通过tryLock由一个线程去更新,其他线程依然使用最近的bucket来更新计数。

  • 同时,每个bucket使用LongAdder而不是AtomicLong进一步降低写的并发,减少执行CAS时循环的次数。



0 0