Spring Cloud Hystrix

简介: Spring Cloud Hystrix

一、为什么要引入Hystrix 的作用?


在微服务架构中,根据业务来拆分成一个个的服务,而服务与服务之间存在着依赖关系 (比如用户调商品, 商品调库存,库存调订单等等),在Spring Cloud中多个微服务之间可以用 RestTemplate+Ribbon 和 Feign 来调用。


在服务之间调用的链路上由于网络原因、资源繁忙或者自身的原因,服务并不能保证100%可用,如果单个服务出 现问题,调用这个服务就会出现线程阻塞,导致响应时间过长或不可用,此时若有大量的请求涌入,容器的线程资 源会被消耗完毕,导致服务瘫痪。服务与服务之间的依赖性,故障会传播,会对整个微服务系统造成灾难性的严重 后果,这就是服务故障的“雪崩”效应。


Hystrix通过隔离服务之间的访问,阻止他们之间的级联故障。

其四大作用:熔断,降级,隔离,监控


二、熔断的原理


默认条件:断路器开启或者关闭的条件


当满足一定的阀值的时候默认10秒内超过20个请求次数


当失败率达到一定的时候默认10秒内超过50%的请求失败


到达以上阀值断路器将会开启


当开启的时候所有请求都不会进行转发


一段时间之后默认是5秒这个时候断路器是半开状态会让其中一个请求进行转发。如果成功断路器会关闭若失败继续开启。


image.png


Closed状态:默认情况关闭,断路器关闭的,所有请求可以正常发起


Open状态:当我们触发熔断以后,开启断路器,处于Open状态,后续5s的所有请求都不会发送到服务器


Half-Open状态:每搁5s会尝试请求,如果5s之后,后续的请求过来后,它会发到远程服务器,如果发现能够正常接收请求,那断路器就变为Closed状态,如果请求结果失败就会继续返回到Open状态,尝试过程中就是Half-Open状态。


降级触发的三种条件:


熔断触发降级;


请求超时触发降级;


资源隔离


-平台隔离,部署隔离,业务隔离,服务隔离,资源隔离


CPU,内存,线程


三、隔离的两种情况(线程池隔离与信号量隔离)


image.png


上面这张图说明了线程池隔离和信号量隔离的主要区别:线程池方式下业务请求线程和执行依赖的服务的线程不是同一个线程;信号量方式下业务请求线程和执行依赖服务的线程是同一个线程。


线程池:

Hystrix通过命令模式对发送请求的对象和执行请求的对象进行解耦,将不同类型的业务请求封装为对应的命令请求。如订单服务查询商品,查询商品请求->商品Command;商品服务查询库存,查询库存请求->库存Command。并且为每个类型的Command配置一个线程池,当第一次创建Command时,根据配置创建一个线程池,并放入ConcurrentHashMap,如商品Command:


final static ConcurrentHashMap<String, HystrixThreadPool> threadPools = new ConcurrentHashMap<String, HystrixThreadPool>();
...
if (!threadPools.containsKey(key)) {
    threadPools.put(key, new HystrixThreadPoolDefault(threadPoolKey, propertiesBuilder));
}


后续查询商品的请求创建Command时,将会重用已创建的线程池。线程池隔离之后的服务依赖关系:


image.png


通过将发送请求线程与执行请求的线程分离,可有效防止发生级联故障。当线程池或请求队列饱和时,Hystrix将拒绝服务,使得请求线程可以快速失败,从而避免依赖问题扩散。


***线程池的主要缺点***是增加了计算开销。每个命令的执行都在单独的线程完成,增加了排队、调度和上下文切换的开销。因此,要使用Hystrix,就必须接受它带来的开销,以换取它所提供的好处。


通常情况下,线程池引入的开销足够小,不会有重大的成本或性能影响。但对于一些访问延迟极低的服务,如只依赖内存缓存,线程池引入的开销就比较明显了,这时候使用线程池隔离技术就不适合了,我们需要考虑更轻量级的方式,如信号量隔离。


信号量隔离:

使用线程池时,发送请求的线程和执行依赖服务的线程不是同一个,而使用信号量时,发送请求的线程和执行依赖服务的线程是同一个,都是发起请求的线程。先看一个使用信号量隔离线程的示例:


public class QueryByOrderIdCommandSemaphore extends HystrixCommand<Integer> {
    private final static Logger logger = LoggerFactory.getLogger(QueryByOrderIdCommandSemaphore.class);
    private OrderServiceProvider orderServiceProvider;
    public QueryByOrderIdCommandSemaphore(OrderServiceProvider orderServiceProvider) {
        super(Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey("orderService"))
                .andCommandKey(HystrixCommandKey.Factory.asKey("queryByOrderId"))
                .andCommandPropertiesDefaults(HystrixCommandProperties.Setter()
                        .withCircuitBreakerRequestVolumeThreshold(10)至少有10个请求,熔断器才进行错误率的计算
                        .withCircuitBreakerSleepWindowInMilliseconds(5000)//熔断器中断请求5秒后会进入半打开状态,放部分流量过去重试
                        .withCircuitBreakerErrorThresholdPercentage(50)//错误率达到50开启熔断保护
                        .withExecutionIsolationStrategy(HystrixCommandProperties.ExecutionIsolationStrategy.SEMAPHORE)
                        .withExecutionIsolationSemaphoreMaxConcurrentRequests(10)));//最大并发请求量
        this.orderServiceProvider = orderServiceProvider;
    }
    @Override
    protected Integer run() {
        return orderServiceProvider.queryByOrderId();
    }
    @Override
    protected Integer getFallback() {
        return -1;
    }
}


实现方式是使用一个原子计数器或信号量来记录当前有多少个线程在运行请求过来了先判断计数器的数值若超过设置的最大线程个数则丢弃该类型的新请求若不超过则执行计数操作请求来计数器+1。


由于Hystrix默认使用线程池做线程隔离,使用信号量隔离需要显示地将属性execution.isolation.strategy设置为ExecutionIsolationStrategy.SEMAPHORE,同时配置信号量个数,默认为10。客户端需向依赖服务发起请求时,首先要获取一个信号量才能真正发起调用,由于信号量的数量有限,当并发请求量超过信号量个数时,后续的请求都会直接拒绝,进入fallback流程。


信号量隔离主要是通过控制并发请求量,防止请求线程大面积阻塞,从而达到限流和防止雪崩的目的。


四、回退降级

降级,通常指务高峰期,为了保证核心服务正常运行,需要停掉一些不太重要的业务,或者某些服务不可用时,执行备用逻辑从故障服务中快速失败或快速返回,以保障主体业务不受影响。Hystrix提供的降级主要是为了容错,保证当前服务不受依赖服务故障的影响,从而提高服务的健壮性。要支持回退或降级处理


熔断触发降级

资源隔离触发降级

请求超时触发降级


主动降级,大促的时候关闭非核心服务.

被动降级, 熔断降级、限流降级


当被AOP切面拦截的时候,判断是否处于熔断状态,判断是否被限流,线程池资源是否被耗尽

熔断的流程:


image.png


image.png


Hystrix的数据统计是采用滑动窗口

滑动窗口,流向控制技术

计数器


image.png


我们可以看到总共10s钟,每个熔断器默认维护了10个bucket,每秒一个bucket,当新的bucket被创建时,最旧的bucket会被抛弃。其中每个blucket维护了请求成功、失败、超时、拒绝的计数器,Hystrix负责收集并统计这些计数器。


五、熔断器的执行流程


image.png


整个流程可以大致归纳为如下几个步骤:


创建HystrixCommand或者HystrixObservableCommand对象

执行 Command

检查请求结果是否被缓存

检查是否开启了短路器

检查 线程池/队列/semaphore 是否已经满

执行 HystrixObservableCommand.construct() or HystrixCommand.run()

计算短路健康状况

调用fallback降级机制

返回依赖请求的真正结果


目录
相关文章
|
4月前
|
监控 负载均衡 Java
深入理解Spring Cloud中的服务网关
深入理解Spring Cloud中的服务网关
|
3月前
|
Java UED 开发者
Spring Boot 降级功能的神秘面纱:Hystrix 与 Resilience4j 究竟藏着怎样的秘密?
【8月更文挑战第29天】在分布式系统中,服务稳定性至关重要。为应对故障,Spring Boot 提供了 Hystrix 和 Resilience4j 两种降级工具。Hystrix 作为 Netflix 的容错框架,通过隔离依赖、控制并发及降级机制增强系统稳定性;Resilience4j 则是一个轻量级库,提供丰富的降级策略。两者均可有效提升系统可靠性,具体选择取决于需求与场景。在面对服务故障时,合理运用这些工具能确保系统基本功能正常运作,优化用户体验。以上简介包括了两个工具的简单示例代码,帮助开发者更好地理解和应用。
70 0
|
4月前
|
设计模式 监控 Java
解析Spring Cloud中的断路器模式原理
解析Spring Cloud中的断路器模式原理
|
2月前
|
XML 监控 Java
Spring Cloud全解析:熔断之Hystrix简介
Hystrix 是由 Netflix 开源的延迟和容错库,用于提高分布式系统的弹性。它通过断路器模式、资源隔离、服务降级及限流等机制防止服务雪崩。Hystrix 基于命令模式,通过 `HystrixCommand` 封装对外部依赖的调用逻辑。断路器能在依赖服务故障时快速返回备选响应,避免长时间等待。此外,Hystrix 还提供了监控功能,能够实时监控运行指标和配置变化。依赖管理方面,可通过 `@EnableHystrix` 启用 Hystrix 支持,并配置全局或局部的降级策略。结合 Feign 可实现客户端的服务降级。
153 23
|
2月前
|
Java 对象存储 开发者
故障隔离与容错处理:Hystrix在Spring Cloud和Netflix OSS中的应用
故障隔离与容错处理:Hystrix在Spring Cloud和Netflix OSS中的应用
52 3
|
4月前
|
资源调度 Java 调度
Spring Cloud Alibaba 集成分布式定时任务调度功能
Spring Cloud Alibaba 发布了 Scheduling 任务调度模块 [#3732]提供了一套开源、轻量级、高可用的定时任务解决方案,帮助您快速开发微服务体系下的分布式定时任务。
14906 29
|
4月前
|
负载均衡 Java Spring
Spring cloud gateway 如何在路由时进行负载均衡
Spring cloud gateway 如何在路由时进行负载均衡
475 15
|
4月前
|
Java Spring
spring cloud gateway在使用 zookeeper 注册中心时,配置https 进行服务转发
spring cloud gateway在使用 zookeeper 注册中心时,配置https 进行服务转发
109 3
|
4月前
|
消息中间件 Java 开发者
Spring Cloud微服务框架:构建高可用、分布式系统的现代架构
Spring Cloud是一个开源的微服务框架,旨在帮助开发者快速构建在分布式系统环境中运行的服务。它提供了一系列工具,用于在分布式系统中配置、服务发现、断路器、智能路由、微代理、控制总线、一次性令牌、全局锁、领导选举、分布式会话、集群状态等领域的支持。
181 5
下一篇
无影云桌面