Hystrix原理讲解
Posted codingjav
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Hystrix原理讲解相关的知识,希望对你有一定的参考价值。
目录
前言:
分布式系统中经常会出现某个基础服务不可用造成整个系统不可用的情况, 这种现象被称为服务雪崩效应. 为了应对服务雪崩, 一种常见的做法是手动服务降级. 而Hystrix的出现,给我们提供了另一种选择.
服务雪崩定义:
服务雪崩效应是一种因 服务提供者 的不可用导致 服务调用者 的不可用,并将不可用 逐渐放大 的过程.如果所示:
上图中, A为服务提供者, B为A的服务调用者, C和D是B的服务调用者. 当A的不可用,引起B的不可用,并将不可用逐渐放大C和D时, 服务雪崩就形成了.
服务雪崩形成的原因:
按照雪崩参与者可以分为调用者和提供者,并可以把造成雪崩分为下面三个阶段来分析原因:
- 服务提供者不可用
- 服务调用者不可用
- 重试增大流量
服务雪崩的每个阶段都可能由不同的原因造成, 比如造成 服务不可用 的原因有:
-
硬件故障
-
程序Bug
-
缓存击穿
-
用户大量请求
硬件故障可能为硬件损坏造成的服务器主机宕机, 网络硬件故障造成的服务提供者的不可访问.
缓存击穿一般发生在缓存应用重启, 所有缓存被清空时,以及短时间内大量缓存失效时. 大量的缓存不命中, 使请求直击后端,造成服务提供者超负荷运行,引起服务不可用.
在秒杀和大促开始前,如果准备不充分,用户发起大量请求也会造成服务提供者的不可用.
而形成 重试加大流量 的原因有:
-
用户重试
-
代码逻辑重试
在服务提供者不可用后, 用户由于忍受不了界面上长时间的等待,而不断刷新页面甚至提交表单.
服务调用端的会存在大量服务异常后的重试逻辑.
这些重试都会进一步加大请求流量.
最后, 服务调用者不可用 产生的主要原因是:
-
同步等待造成的资源耗尽
当服务调用者使用 同步调用 时, 会产生大量的等待线程占用系统资源. 一旦线程资源被耗尽,服务调用者提供的服务也将处于不可用状态, 于是服务雪崩效应产生了.
雪崩应对策略:
针对造成服务雪崩的不同原因, 可以使用不同的应对策略:
-
流量控制
-
改进缓存模式
-
服务自动扩容
-
服务调用者降级服务
流量控制 的具体措施包括:
-
网关限流
-
用户交互限流
-
关闭重试
改进缓存模式:
- 缓存预加载
- 同步改异步
自动扩容:
- 增加机器数量
- 升级硬件配置
使用Hystrix解决雪崩:
特色:
Hystrix是一个低延迟和容错的第三方组件库。旨在隔离远程系统、服务和第三方库的访问点。官网上已经停止维护并推荐使用resilience4j:https://github.com/resilience4j/resilience4j。 但是国内的话我们有springcloud alibaba。
Hystrix 通过隔离服务之间的访问来实现分布式系统中延迟及容错机制来解决服务雪崩场景并且基于hystrix可以提供备选方案(fallback)。
-
对网络延迟及故障进行容错
-
阻断分布式系统雪崩
-
快速失败并平缓恢复
-
服务降级
-
实时监控、警报
设计原则
- 资源隔离
- 熔断器
- 命令模式
资源隔离:
这种资源隔离减少风险的方式被称为:Bulkheads(舱壁隔离模式).Hystrix将同样的模式运用到了服务调用者上.
比如调用三个依赖服务会共享商品详情服务的线程池. 如果其中的商品评论服务不可用, 就会出现线程池里所有线程都因等待响应而被阻塞, 从而造成服务雪崩. 如图所示:
Hystrix通过将每个依赖服务分配独立的线程池进行资源隔离, 从而避免服务雪崩.
如下图所示, 当商品评论服务不可用时, 即使商品服务独立分配的20个线程全部处于同步等待状态,也不会影响其他依赖服务的调用.
熔断器模式:
熔断器模式定义了熔断器开关相互转换的逻辑:
服务的健康状况 = 请求失败数 / 请求总数.
熔断器开关由关闭到打开的状态转换是通过当前服务健康状况和设定阈值比较决定的.
-
当熔断器开关关闭时, 请求被允许通过熔断器. 如果当前健康状况高于设定阈值, 开关继续保持关闭. 如果当前健康状况低于设定阈值, 开关则切换为打开状态.
-
当熔断器开关打开时, 请求被禁止通过.
-
当熔断器开关处于打开状态, 经过一段时间后, 熔断器会自动进入半开状态, 这时熔断器只允许一个请求通过. 当该请求调用成功时, 熔断器恢复到关闭状态. 若该请求失败, 熔断器继续保持打开状态, 接下来的请求被禁止通过.
熔断器的开关能保证服务调用者在调用异常服务时, 快速返回结果, 避免大量的同步等待. 并且熔断器能在一段时间后继续侦测请求执行结果, 提供恢复服务调用的可能.
命令模式:
Hystrix使用命令模式(继承HystrixCommand类)来包裹具体的服务调用逻辑(run方法), 并在命令模式中添加了服务调用失败后的降级逻辑(getFallback).
同时我们在Command的构造方法中可以定义当前服务线程池和熔断器的相关参数. 如下代码所示:
public class Service1HystrixCommand extends HystrixCommand<Response> {
private Service1 service;
private Request request;
public Service1HystrixCommand(Service1 service, Request request){
supper(
Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey("ServiceGroup"))
.andCommandKey(HystrixCommandKey.Factory.asKey("servcie1query"))
.andThreadPoolKey(HystrixThreadPoolKey.Factory.asKey("service1ThreadPool"))
.andThreadPoolPropertiesDefaults(HystrixThreadPoolProperties.Setter()
.withCoreSize(20))//服务线程池数量
.andCommandPropertiesDefaults(HystrixCommandProperties.Setter()
.withCircuitBreakerErrorThresholdPercentage(60)//熔断器关闭到打开阈值
.withCircuitBreakerSleepWindowInMilliseconds(3000)//熔断器打开到关闭的时间窗长度
))
this.service = service;
this.request = request;
);
}
@Override
protected Response run(){
return service1.call(request);
}
@Override
protected Response getFallback(){
return Response.dummy();
}
}
在使用了Command模式构建了服务对象之后, 服务便拥有了熔断器和线程池的功能.
Hystrix的内部处理逻辑
下图为Hystrix服务调用的内部逻辑:
-
构建Hystrix的Command对象, 调用执行方法.
-
Hystrix检查当前服务的熔断器开关是否开启, 若开启, 则执行降级服务getFallback方法.
-
若熔断器开关关闭, 则Hystrix检查当前服务的线程池是否能接收新的请求, 若超过线程池已满, 则执行降级服务getFallback方法.
-
若线程池接受请求, 则Hystrix开始执行服务调用具体逻辑run方法.
-
若服务执行失败, 则执行降级服务getFallback方法, 并将执行结果上报Metrics更新服务健康状况.
-
若服务执行超时, 则执行降级服务getFallback方法, 并将执行结果上报Metrics更新服务健康状况.
-
若服务执行成功, 返回正常结果.
-
若服务降级方法getFallback执行成功, 则返回降级结果.
-
若服务降级方法getFallback执行失败, 则抛出异常.
以上是关于Hystrix原理讲解的主要内容,如果未能解决你的问题,请参考以下文章
springcloud报错-------关于 hystrix 的异常 FallbackDefinitionException:fallback method wasn't found(代码片段
SpringCloud H版 Hystrix 服务熔断限流讲解