温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

何为Hystrix

发布时间:2021-10-23 11:03:18 来源:亿速云 阅读:136 作者:iii 栏目:编程语言

这篇文章主要讲解了“何为Hystrix”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“何为Hystrix”吧!

什么是服务雪崩?

在分布式架构中,很常见的一个情形就是某一个请求需要调用多个服务。

如客户端访问 user 服务,而 user 服务需要调用 order 服务,order 服务需要调用 goods 服务,由于网络原因或者自身的原因,如果 order 服务或者 goods 服务不能及时响应,user 服务将处于阻塞状态,直到 order 服务 goods 服务响应。

此时若有大量的请求涌入,容器的线程资源会被消耗完毕,导致服务瘫痪。

服务与服务之间的依赖性,故障会传播,造成连锁反应,会对整个微服务系统造成灾难性的严重后果,这就是服务故障的“雪崩”效应。

何为Hystrix

1.如图所示,此时的系统正在愉快的运行中。

2.突然这个时候,goods服务节点的网络发生了故障。goods服务节点瘫痪,goods服务不可用。

3.由于good服务瘫痪导致order服务向goods服务发送的请求得不到返回,一直处于阻塞,此时user服务仍然一直 向order服务发送请求,最终导致order服务节点的资源耗尽,order服务节点瘫痪,order服务不可用。

4.由于good服务瘫痪导致order服务向goods服务发送的请求得不到返回,一直处于阻塞,此时user服务仍然一直 向order服务发送请求,最终导致order服务节点的资源耗尽,也瘫痪掉。此时user服务向order服务发送的请求同样也得不到返回,而客户端依然源源不断的向user服务节点发送请求,最终user服务节点和order服务节点一样,由于资源耗尽导致服务器瘫痪,user服务也不可用。

如上所述,一个服务节点的瘫痪,导致整条链路的服务节点都瘫痪的情形,我们称之为服务雪崩。

为什么会产生服务雪崩?

流量激增:比如异常流量、用户重试导致系统负载升高;

缓存穿透:假设A为client端,B为Server端,假设A系统请求都流向B系统,请求超出了B系统的承载能力,就会造成B系统崩溃;

程序有Bug:代码循环调用的逻辑问题,资源未释放引起的内存泄漏等问题;

硬件故障:比如宕机,机房断电,光纤被挖断等。

数据库严重瓶颈,比如:长事务、慢sql等。

线程同步等待:系统间经常采用同步服务调用模式,核心服务和非核心服务共用一个线程池和消息队列。如果一个核心业务线程调用非核心线程,这个非核心线程交由第三方系统完成,当第三方系统本身出现问题,导致核心线程阻塞,一直处于等待状态,而进程间的调用是有超时限制的,最终这条线程将断掉,也可能引发雪崩。

有什么办法解决服务雪崩?

当发生突发流量激增的情况下,我们可以使用自动扩容,或者是在负载均衡器中添加服务限流功能

对于缓存穿透造成的服务雪崩问题,可以通过缓存预加载、缓存异步加载等方式来解决。

对于程序bug,emmm...,只能改bug了。

对于数据库查询时间过长导致的服务雪崩可以进行sql优化,硬件升级等。

对于硬件故障造成的服务雪崩, ,跨机房路由,异地多活等方式。

对于不同的造成服务雪崩的场景,有着很多不同的解决方案,但是没有一个通用的解决方案可以解决所有的问题。

在通过大量的实践证明,线程同步等待是最常见引发的雪崩效应的场景,此刻,本章节的主人公Hystrix将粉墨登场,我们将详细介绍如何使用Hystrix做故障隔离,熔断器机制等可以解决依赖服务不可用的问题。

Hystrix整体认知

Hystrix是一个用于处理微服务架构中的服务之间调用故障和容错的开源库。

在微服务架构里,各个服务之间的调用都可能会失败,比如超时、异常等。

Hystrix能够保证在一个依赖出问题的情况下,不会导致整个服务链路全线崩溃,提高微服务架构的可用性。

Hystrix,我们又称“断路器”,其本身是一种开关装置,当某个服务单元发生故障之后,通过断路器的故障监控(类似熔断保险丝),向调用方返回一个符合预期的、可处理的备选响应(FallBack),而不是长时间的等待或者抛出调用方无法处理的异常,这样就保证了服务调用方的线程不会被长时间、不必要地占用,从而避免了故障在分布式系统中的蔓延,乃至雪崩。

Hystrix设计目标,实现方式

设计目标

(1)对依赖服务调用时出现的调用延迟和调用失败进行控制和容错保护。
(2)阻止某一个依赖服务的故障在整个系统中蔓延,服务A->服务B->服务C,服务C故障了,服务B也故障了,服务A故障了,整个系统全部故障,整体宕机。(3)提供fail-fast(快速失败)和快速恢复的支持。
(4)提供fallback优雅降级的支持。
(5)支持近实时的监控、报警以及运维操作。

实现方式

  1. 通过hystrixCommand或者HystrixObservableCommand来封装对外部依赖的访问请求,这个访问请求一般会运行在独立的线程中。

  2. 对于超出我们设定的阈(yu)值服务调用,直接进行超时返回,不允许它长时间的阻塞。

  3. 对每一个依赖服务进行资源隔离。通过线程池或者是semaphore这两种方式。

  4. 对依赖服务被调用的成功次数,失败次数,拒绝次数,超时次数进行统计。

  5. 如果对某一个依赖服务的调用失败次数超过了一点的阈值,Hystrix自动进行熔断,并在一段时间内对该服务的调用直接进行降级,一段时间后再自动尝试恢复

  6. 当对一个服务调用出现失败、被拒绝、超时、短路等异常情况时,自动调用fallback降级机制。

  7. 对属性和配置的修改提供近实时的支持

Hystrix工作流程

首先我们看一下管网的Hystrix工作流程图:

何为Hystrix

下面我们针对这张图详细解读下Hystrix的工作流程。

1.每次调用都会创建HystrixCommand或者HystrixObservableCommand对象

2.执行execute(observe)或queue(toObservable)做同步\异步调用

3.检查请求结果是否被缓存,如果缓存直接返回

4.检查是否开启了断路器,如果开启直接跳到步骤8

5.检查线程池/信号量是否跑满,如果跑满进入步骤8

6.执行 HystrixObservableCommand.construct() or HystrixCommand.run(),如果执行异常或者调用超时直接跳到步骤8

7.计算断路器状态,所有的运行状态(成功, 失败, 拒绝,超时)上报给断路器,用于统计从而判断断路器状态

8.调用fallback降级机制,通过上述步骤会有(熔断器打开,线程池/信号量跑满,调用超时,调用失败)四种情况会进行降级处理

9.返回依赖请求的真正结果

工作流程详解

第一步,创建HystrixCommand或者HystrixObservableCommand对象

HytrixCommand和HystrixObservableCommand包装了对外部依赖访问的逻辑。

整个流程的第一个步骤就是实例化HystrixCommand或者HystrixObservableCommand对象。

在构造这两个Command对象时,可以通过构造方法传递任何执行过程中需要的参数。

如果对外部依赖调用只返回一个结果值,那么可以实例化一个HystrixCommand对象。

HystrixCommand command = newHystrixCommand(arg1, arg2);

如果在调用外部依赖时需要返回多个结果值时,可以实例化一个HystrixObservableCommand对象

HystrixObservableCommand command = newHystrixObservableCommand(arg1, arg2);

第二步,执行execute(observe)或queue(toObservable)做同步\异步调用

HystrixCommand主要是使用以下两个命令

execute():同步执行,从依赖的服务返回一个单一的结果对象,或者是在发生错误的时候抛出异常。

queue():异步执行,直接返回一个Future对象,其中包含了服务执行结束时要返回的单一结果对象。

HystrixObservableCommand使用以下两个命令

observe():返回Observable对象,返回 Observable 对象,立即发出请求,在依赖服务响应(或者抛出异常/超时)时,通过注册的 Subscriber 得到返回结果,它是一个Hot Observable。

toObservable():返回Observable对象,但只有在订阅该对象时,才会发出请求,然后在依赖服务响应(或者抛出异常/超时)时,通过注册的 Subscriber 得到返回结果,它是一个Cold Observable。

第三步,检查请求结果是否被缓存,如果缓存直接返回

若当前命令的请求缓存功能是被启用的,并且该命令缓存命中,那么缓存的结果会立即以Observable对象的形式返回。

这个结果缓存的好处为:

1、在同一个请求上下文中,可以减少使用相同参数请求原始服务的开销。
2、请求缓存在步骤5执行之前生效,所以可以有效减少不必要的线程开销。

第四步,检查是否开启了断路器

在缓存没有被命中时,Hystrix会在执行步骤5之前先检查断路器是否被打开。如果打开了,Hystrix不会执行任何命令执行跳转到步骤8

断路器开关控制条件:
    1.对外部依赖调用的次数满足配置的阈值    2.对外部依赖调用发生错误的比率满足配置的阈值

在满足以上两个条件时,断路器打开熔断开关,之后所有对外部依赖调用都将被直接断开。

在开关打开时长超过试探窗口期后,断路器将尝试放行部分外部依赖的调用,

根据试探的结果决定重新开启或者关闭熔断开关。

第五步,检查线程池/信号量是否跑满

我们知道,Hystrix引入了线程池和信号量两种方式实现资源隔离机制。如果此时命令对应的线程池或队列或信号量已经满了,直接跳转到步骤8。

第六步,执行 HystrixObservableCommand.construct() or HystrixCommand.run()

Hystrix会根据我们编写的方法来决定采取什么方式去请求依赖服务。

1.HystrixCommand.run()——返回单个响应或抛出异常。

2.HystrixObservableCommand.construct()——返回 Observable 对象来发射多个结果,或通过onError发送错误通知。

如果run()或construct()方法执行时长超过了命令的超时阀值,其线程将抛出一个TimeoutException(或者在一个单独的线程抛出,如果命令没有运行在它自己的线程)。

这种情况下 Hystrix转接到fallback处理逻辑(第8步)。

并且如果该命令没有取消或中断,它将放弃run()或construct()方法最终的返回值。

如果命令没有抛出异常并且返回了响应,Hystrix 将会在执行一些日志记录和度量报告之后返回结果给调用者。

如果是通过run()运行,Hystrix 将返回 Observable 发射单个结果,然后发送一个onCompleted的通知;如果是通过construct()运行,Hystrix 直接返回该方法产生的Observable对象。

第七步,计算断路器状态

Hystrix会将每一个依赖服务的调用成功,失败,拒绝,超时,等事件,都会发送给circuit breaker断路器。

HystrixCircuitBreaker通过维护一系列的counter记录外部依赖请求的执行情况。

断路器根据维护的这些信息,在符合触发条件下开启断路功能,在条件合适的时候关闭断路开关。

如果打开了断路器,那么在一段时间内就会直接短路,然后如果在之后第一次检查发现调用成功了,就关闭断路器。

第八步,调用fallback降级机制

通过对上述步骤的详细解读,我们发现有以下几种情况是会调用fallback降级机制的。
1.断路器打开

2.线程池或者信号量已经满了

3.command执行异常

4.执行超时

在服务降级逻辑中,需要实现一个通用的响应结果,并且该结果的处理逻辑应当是从缓存或是根据一些静态逻辑来获取,而不是依赖网络请求获取。

如果一定要在服务降级逻辑中包含网络请求,那么该请求也必须包装在HystrixCommand或HystrixObservableCommand中,从而形成级联的降级策略。

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

1.在 HystrixCommand 中,在 HystrixCommand.getFallback()方法中提供自定义的回调逻辑,方法返回单个回调值。 

2.在 HystrixObservableCommand 中,在HystrixObservableCommand.resumeWithFallback() 方法中提供自定义的回调逻辑,方法返回一个Observable对象来发射一个或多个降级结果

如果fallback返回了结果,那么Hystrix就会返回这个结果。

对于HystrixCommand,会返回一个Observable对象,其中会发返回对应的结果;

对于HystrixObservableCommand,会返回一个原始的Observable对象。

如果没有实现fallback,或者是fallback抛出了异常,Hystrix会返回一个Observable,但是不会返回任何数据。

不同的command执行方式,其fallback为空或者异常时的返回结果不同

1.对于execute(),直接抛出异常

2.对于queue(),返回一个Future,调用get()时抛出异常

3.对于observe(),返回一个Observable对象,但是调用subscribe()方法订阅它时,抛出调用者的onError方法

4.对于toObservable(),返回一个Observable对象,但是调用subscribe()方法订阅它时,抛出调用者的onError方法

第九步,返回依赖请求的真正结果

如果Hystrix命令执行成功,它将以Observable形式返回响应给调用者。根据你在步骤2的调用方式不同,在返回Observablez之前可能会做一些转换。

何为Hystrix

execute():通过调用queue()来得到一个Future对象,然后调用get()方法来获取Future中包含的值。

queue():将Observable转换成BlockingObservable,在将BlockingObservable转换成一个Future。

observe():订阅返回的Observable,并且立即开始执行命令的逻辑。

toObservable():返回一个没有改变的Observable,你必须订阅它,它才能够开始执行命令的逻辑。

上述就是整个Hystrix的工作流程,当然没有很深入的讲解,但是还是建议多看几遍,我面试的时候碰到好几次让我简述Hystrix工作流程,多看几遍,记在心里,面试不慌。

Hystrix使用框架搭建

当然了,Hystrix也能和Feign 和 Zuul 的集成使用,这些在这里就不赘述了,后续介绍Feign和Zuul的文章中会详细说明。

本文主要介绍HystrixCommand 注解方式的使用。

首先我们搭建一个HystrixClient项目。

添加配置文件application.properties何为Hystrix

何为Hystrix

新建RestConfiguration类,用来全局配置RestTemplate。

何为Hystrix

新建HystrixController类

然后在启动类的上添加@EnableHystrix注解。

何为Hystrix

改造上一篇万字详解Ribbon架构,针对面试高频题多角度细说Ribbon中提供的OrderService,让代码休眠5秒后在返回。

在HystrixController中的三个方法中分别配置了2000ms,10000ms,10000ms如果没有返回结果,那么将直接回调用我们指定的fallback。

OrderService

何为Hystrix

上述三步,基本的Hystrix使用框架就搭建完成了,然后我们启动上一篇万字详解Ribbon架构,针对面试高频题多角度细说Ribbon中提到的Eureka-Server,并按照上篇文章的启动方式,分别启动OrderServeice的7777,8888,9999三个端口,此时我们打开 http://localhost:8761/ 页面,我们发现已经有三个服务名为order-service,端口号分别7777,8888,9999的服务注册了进来。

何为Hystrix

最后我们启动HystrixClient启动类,然后我们先访问设置超时时间为10000ms的 localhost:8088/test2 ,因为我们在OrderService中设置的休眠时间为3000ms所以能在超时时间内返回请求,所以不用调用fallback。

Hystrix核心配置详解

Execution相关的属性的配置

hystrix.command.default.execution.isolation.strategy 

隔离策略,默认是Thread, 可选Thread,Semaphore

hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds 

命令执行超时时间,默认1000ms。

hystrix.command.default.execution.timeout.enabled 

执行是否启用超时,默认启用true。

hystrix.command.default.execution.isolation.thread.interruptOnTimeout

发生超时是是否中断,默认true。

hystrix.command.default.execution.isolation.semaphore.maxConcurrentRequests 

理论上选择semaphore size的原则和选择thread size一致,但选用semaphore时每次执行的单元要比较小且执行速度快(ms级别),否则的话应该用thread。semaphore应该占整个容器(tomcat)的线程池的一小部分。

Fallback相关配置

hystrix.command.default.fallback.isolation.semaphore.maxConcurrentRequests 

如果并发数达到该设置值,请求会被拒绝和抛出异常并且fallback不会被调用。默认10。

hystrix.command.default.fallback.enabled 

当执行失败或者请求被拒绝,是否会尝试调用hystrixCommand.getFallback() 。默认true。

Metrics相关属性配置

hystrix.command.default.metrics.rollingStats.timeInMilliseconds

设置统计的时间窗口值的,毫秒值,circuit break 的打开会根据1个rolling window的统计来计算。若rolling window被设为10000毫秒,则rolling window会被分成n个buckets,每个bucket包含success,failure,timeout,rejection的次数的统计信息。默认10000。

hystrix.command.default.metrics.rollingStats.numBuckets 

设置一个rolling window被划分的数量,若numBuckets=10,rolling window=10000,那么一个bucket的时间即1秒。必须符合rolling window % numberBuckets == 0。默认10。

hystrix.command.default.metrics.rollingPercentile.enabled

执行时是否enable指标的计算和跟踪,默认true。

hystrix.command.default.metrics.rollingPercentile.timeInMilliseconds

设置rolling percentile window的时间,默认60000。

hystrix.command.default.metrics.rollingPercentile.numBuckets

设置rolling percentile window的numberBuckets。逻辑同上。默认6。

hystrix.command.default.metrics.rollingPercentile.bucketSize

如果bucket size=100,window=10s,若这10s里有500次执行,只有最后100次执行会被统计到bucket里去。增加该值会增加内存开销以及排序的开销。默认100。

hystrix.command.default.metrics.healthSnapshot.intervalInMilliseconds

记录health 快照(用来统计成功和错误绿)的间隔,默认500ms。

ThreadPool 相关属性配置

hystrix.threadpool.default.coreSize

并发执行的最大线程数,默认10。

hystrix.threadpool.default.maxQueueSize

BlockingQueue的最大队列数,当设为-1,会使用SynchronousQueue,值为正时使用LinkedBlcokingQueue。该设置只会在初始化时有效,之后不能修改threadpool的queue size,除非reinitialising thread executor。默认-1。

hystrix.threadpool.default.queueSizeRejectionThreshold

即使maxQueueSize没有达到,达到queueSizeRejectionThreshold该值后,请求也会被拒绝。因为maxQueueSize不能被动态修改,这个参数将允许我们动态设置该值。if maxQueueSize == -1,该字段将不起作用。

hystrix.threadpool.default.keepAliveTimeMinutes

如果corePoolSize和maxPoolSize设成一样(默认实现)该设置无效。

hystrix.threadpool.default.metrics.rollingStats.timeInMilliseconds

线程池统计指标的时间,默认10000。

hystrix.threadpool.default.metrics.rollingStats.numBuckets

将rolling window划分为n个buckets,默认10。

Hystrix容错机制之回退降级‍‍‍‍‍‍‍‍‍

1.什么是降级?

降级,通常指事务高峰期,为了保证核心服务正常运行,需要停掉一些不太重要的业务,或者某些服务不可用时,执行备用逻辑从故障服务中快速失败或快速返回,以保障主体业务不受影响。

Hystrix提供的降级主要是为了容错,保证当前服务不受依赖服务故障的影响,从而提高服务的健壮性。

要支持回退或降级处理,可以重写HystrixCommand的getFallBack方法或HystrixObservableCommand的resumeWithFallback方法。

2.什么情况下才会走降级?

从Hystrix的工作流程图中我们可以看到以下情况会走降级逻辑。
1.断路器打开
2.线程池或者信号量已经满了
3.command执行异常
4.执行超时

3.回退降级有哪些处理方式?

  1. 快速失败:发生故障后直接抛出,不做处理。

  2. 无声失败:发生故障后,返回无意义内容,如null,空Map等,故障会被屏蔽。

  3. 静态失败:这种配置下,发生故障会返回静态的默认值,如返回值是boolean,则结果为默认true。

  4. Stubbed:这种配置适用于返回值是一个复合对象的情形,发生故障时,会手动创建一个复合对象的实例,实例中往往包含了一些默认值或错误信息。

  5. 依赖缓存:这种情况下,当下层服务故障时,会从缓存中取得之前的旧数据供使用。

  6. 主次模式:这是回退降级的一种特殊使用方法。

主次模式解释:

有时候,我们可能会遇到这样的场景。针对某个业务,可能会有两种处理方案,A方案高效,但是没有经过规模化测试,不敢保证可靠性。B方案保守,虽然效率较低,但是不会出现。这时候,我们就可以尝试采用主次模式。主流程基于A方案运行,fallback基于B方案运行。在运行过程中,如不出错,则一直使用A方案,一时出错,可通过回退降级,迅速切换为B方案,以避免问题的不受控扩散。

Hystrix监控系统搭建

什么是Hystrix Dashboard?

Hystrix提供了准实时的调用监控(Hystrix DashBoard),Hystrix会持续的记录通过Hystrix发起的请求的执行信息,以统计报表和图形的形式展示给客户,包括每秒执行多少,请求多少成功,请求失败多少等。

Netflix通过Hystrix-metics-event-stream项目实现了对以上指标的监控,SpringCloud也提供了Hystrix DashBoard的整合,对监控内容转化成可视化的界面,以便于用户能够直接的看到服务和集群的状态,在实际使用中,我们往往还要结合Turbine来使用。

开始搭建Hystrix Dashboard

Hystrix Dashboard的搭建其实很简单,分为三步:

  1. 创建监控Hystrix Dashboard项目模块

  2. 配置application.yml

  3. 配置启动类

首先我们创建一个HystrixDashboard项目,配置pom.xml文件如下

何为Hystrix

配置端口为9001

server.port = 9001

配置启动类,添加@EnableHystrixDashboard注解

何为Hystrix

启动后访问http://localhost:9001/hystrix只要我们能看到一只豪猪就说明启动成功了。

何为Hystrix

感谢各位的阅读,以上就是“何为Hystrix”的内容了,经过本文的学习后,相信大家对何为Hystrix这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是亿速云,小编将为大家推送更多相关知识点的文章,欢迎关注!

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI