Hystrix 能使你的系统在出现依赖服务失效的时候,通过隔离系统所依赖的服务,防止服务级联失败,同时提供失败回退机制,更优雅地应对失效,并使你的系统能更快地从异常中恢复。

Hystrix能做什么?

  • 在通过第三方客户端访问(通常是通过网络)依赖服务出现高延迟或者失败时,为系统提供保护和控制

  • 在分布式系统中防止级联失败

  • 快速失败(Fail fast)同时能快速恢复

  • 提供失败回退(Fallback)和优雅的服务降级机制

  • 提供近实时的监控、报警和运维控制手段

Hystrix设计原则?

  • 防止单个依赖耗尽容器(例如 Tomcat)内所有用户线程

  • 降低系统负载,对无法及时处理的请求快速失败(fail fast)而不是排队

  • 提供失败回退,以在必要时让失效对用户透明化

  • 使用隔离机制(例如『舱壁』/『泳道』模式,熔断器模式等)降低依赖服务对整个系统的影响

  • 针对系统服务的度量、监控和报警,提供优化以满足近实时性的要求

  • 在 Hystrix 绝大部分需要动态调整配置并快速部署到所有应用方面,提供优化以满足快速恢复的要求

  • 能保护应用不受依赖服务的整个执行过程中失败的影响,而不仅仅是网络请求

Hystrix实现原理-命令模式

  • 将所有请求外部系统(或者叫依赖服务)的逻辑封装到 HystrixCommand或者HystrixObservableCommand(依赖RxJava)对象中

  • Run()方法为要实现的业务逻辑,这些逻辑将会在独立的线程中被执行当请求依赖服务时出现拒绝服务、超时或者短路(多个依赖服务顺序请求,前面的依赖服务请求失败,则后面的请求不会发出)时,执行该依赖服务的失败回退逻辑(Fallback) 

Hystrix实现原理-舱壁模式

  • 货船为了进行防止漏水和火灾的扩散,会将货仓分隔为多个,当发生灾害时,将所在货仓进行隔离就可以降低整艘船的风险。

Hystrix实现原理-隔离策略

  • 应用在复杂的分布式结构中,可能会依赖许多其他的服务,并且这些服务都不可避免地有失效的可能。如果一个应用没有与依赖服务的失效隔离开来,那么它将有可能因为依赖服务的失效而失效。

  • Hystrix将货仓模式运用到了服务调用者上。为每一个依赖服务维护一个线程池(或者信号量),当线程池占满,该依赖服务将会立即拒绝服务而不是排队等待。

  • 每个依赖服务都被隔离开来,Hystrix 会严格控制其对资源的占用,并在任何失效发生时,执行失败回退逻辑。 

Hystrix实现原理-观察者模式

  • Hystrix通过观察者模式对服务进行状态监听。

  • 每个任务都包含有一个对应的Metrics,所有Metrics都由一个ConcurrentHashMap来进行维护,Key是CommandKey.name() 

  • 在任务的不同阶段会往Metrics中写入不同的信息,Metrics会对统计到的历史信息进行统计汇总,供熔断器以及Dashboard监控时使用。 

Metrics

  • Metrics内部又包含了许多内部用来管理各种状态的类,所有的状态都是由这些类管理的

  • 各种状态的内部也是用ConcurrentHashMap来进行维护的 

    如:HealthCountsStream是用来统计任务失败率的一个类 

    而每个状态管理类内部又包含了各自的真实转态信息 
    如HealthCountsStream保存的信息的一部分如下: 

Metrics如何统计

Metrics在统计各种状态时,时运用滑动窗口思想进行统计的,在一个滑动窗口时间中又划分了若干个Bucket(滑动窗口时间与Bucket成整数倍关系),滑动窗口的移动是以Bucket为单位进行滑动的。 
如:HealthCounts 记录的是一个Buckets的监控状态,Buckets为一个滑动窗口的一小部分,如果一个滑动窗口时间为 t ,Bucket数量为 n,那么每t/n秒将新建一个HealthCounts对象。 

Hystrix实现原理-熔断机制

  • 熔断是参考电路而产生的一种保护性机制,即系统中如果存在某个服务失败率过高时,将开启熔断器,对于后续的调用,不在继续请求服务,而是进行Fallback操作。

  • 熔断所依靠的数据即是Metrics中的HealthCount所统计的错误率。 
    一个命令的调用过程如图所示:

熔断器的判断流程:

1.一个命令执行前会先运行allowRequest()函数。 
allowRequest()函数内部为:

  • 先查看熔断器是否强制开启(ForceOpen()),如果开启则拒绝

  • 再查看熔断器是否强制关闭(ForceClosed()),如果强制关闭则允许Request,否则进一步判断

  • 先做isOpen(),判断熔断器是否开启,如果开启则拒绝访问,如果开启则进一步判断

  • 再做allowSingleTest(),熔断器休眠期过后,允许且只允许一个请求,如果这个请求正确执行,则熔断器关闭,如果执行失败,则熔断器再次开启,进入新的熔断周期。

 

如何判断超时

在运行对应的command时,Hystrix会注册一个Timer到一个定时线程池中,当超时后会启用一个HystrixTimer线程来终止的执行。

线程池的管理是用ThreadPoolExecutor来实现的,当线程池和阻塞队列都满后会抛出RejectedExecutionException,捕获该异常并进行相应状态的处理。

Note:除此之外由程序错误导致的异常,断路器打开都可以导致任务失败进入Fallback

失败降级

Hystrix提供了失败降级策略,当命令执行失败时,Hystrix 将会执行失败回退逻辑。失败回退逻辑包含了通用的回应信息,这些回应从内存缓存中或者其他固定逻辑中得到,而不应有任何的网络依赖。 
如果一定要在失败回退逻辑中包含网络请求,必须将这些网络请求包装在另一个 HystrixCommand 或 HystrixObservableCommand 中。 
失败降级也有频率限时,如果同一fallback短时间请求过大,则会抛出拒绝异常。

缓存机制

除了第一次请求需要真正访问依赖服务以外,后续请求全部从缓存中获取,可以保证在同一个用户请求内,不会出现依赖服务返回不同的回应的情况,且避免了不必要的线程执行。 
缓存在命令内部,且有一个ConcurrentHashMap进行管理 
 
使用缓存需要重写父类的getCacheKey方法

配置

Command

设置隔离策略
execution.isolation.strategy = THREAD 设置超时时间
execution.isolation.thread.timeoutInMilliseconds = 1000 信号量隔离策略设置最大并发请求数(仅在信号量隔离策略下生效)
execution.isolation.semaphore.maxConcurrentRequests = 10 设置最大Fallback数量
fallback.isolation.semaphore.maxConcurrentRequests = 10 设置熔断器滑动窗口最小任务
circuitBreaker.requestVolumeThreshold = 20 设置熔断器持续时间
circuitBreaker.sleepWindowInMilliseconds = 5000 设置触发熔断器的失败任务阈值(百分比)
circuitBreaker.errorThresholdPercentage = 50 设置Metrics监视器的范围时间(过去多少ms内)
metrics.rollingStats.timeInMilliseconds = 10000 设置监视器内桶的数量(将监视器范围划分为若干块)
metrics.rollingStats.numBuckets= 10123456789101112131415161718192021222324252627
 

ThreadPool

设置线程池容量
coreSize = 10 设置阻塞队列长度(优先级高于queueSizeRejectionThreshold,且一旦初始化就不能更改 )
maxQueueSize = -1 动态设置阻塞队列长度
queueSizeRejectionThreshold = 5 空闲线程存活时间
keepAliveTimeMinutes= 1 线程池监控窗口时间范围(10s内)
metrics.rollingStats.timeInMilliseconds = 10000 设置线程池监控滑动窗口的桶数量
metrics.rollingStats.numBuckets = 500123456789101112131415161718
 

Note:窗口时间必须为桶数量的整数倍,否则会抛出异常

Dashboard

1.Hystrix 自带了一个dashboard,用来监控熔断信息. 
2.Dashboard可以监测哪些数据? 
3.使用turbine可以监控集群.

使用Turbine聚合的服务器集群

遇到问题

压测过不了,提高阻塞队列和线程池无效,增加fallback容量解决。 
fallback.isolation.semaphore.maxConcurrentRequests = 100

Hystrix配置简单说明

Hystrix属性的4中优先级

1. 内置全局默认值(Global default from code)

如果下面3种都没有设置,默认是使用此种,后面用“默认值”代指这种。

2. 动态全局默认属性(Dynamic global default property)

可以通过属性配置来更改全局默认值,后面用“默认属性”代指这种。

3. 内置实例默认值(Instance default from code)

在代码中,设置的属性值,后面用“实例默认”来代指这种。

4. 动态配置实例属性(Dynamic instance property)

可以针对特定的实例,动态配置属性值,来代替前面三种,后面用“实例属性”来代指这种。

优先级:1 < 2 < 3 < 4

命令属性

执行

execution.isolation.strategy

设置HystrixCommand.run()的隔离策略,有两种选项:

THREAD —— 在固定大小线程池中,以单独线程执行,并发请求数受限于线程池大小。

SEMAPHORE —— 在调用线程中执行,通过信号量来限制并发量。

默认值:THREAD(ExecutionIsolationStrategy.THREAD)

可选值:THREAD,SEMAPHORE

默认属性:hystrix.command.default.execution.isolation.strategy

实例属性:

hystrix.command.HystrixCommandKey.execution.isolation.strategy

实例默认的设置:

// to use thread isolation

HystrixCommandProperties.Setter()

.withExecutionIsolationStrategy(ExecutionIsolationStrategy.THREAD)

// to use semaphore isolation

HystrixCommandProperties.Setter()

.withExecutionIsolationStrategy(ExecutionIsolationStrategy.SEMAPHORE)

execution.isolation.thread.timeoutInMilliseconds

设置调用者等待命令执行的超时限制,超过此时间,HystrixCommand被标记为TIMEOUT,并执行回退逻辑。

注意:超时会作用在HystrixCommand.queue(),即使调用者没有调用get()去获得Future对象。

默认值:1000(毫秒)

默认属性:hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds

实例属性:hystrix.command.HystrixCommandKey.execution.isolation.thread.timeoutInMilliseconds

实例默认的设置:HystrixCommandProperties.Setter()

.withExecutionTimeoutInMilliseconds(int value)

execution.timeout.enabled

设置HystrixCommand.run()的执行是否有超时限制。

默认值:true

默认属性:hystrix.command.default.execution.timeout.enabled

实例属性:hystrix.command.HystrixCommandKey.execution.timeout.enabled

实例默认的设置:

HystrixCommandProperties.Setter()

.withExecutionTimeoutEnabled(boolean value)

execution.isolation.thread.interruptOnTimeout

设置HystrixCommand.run()的执行是否在超时发生时被中断。

默认值:true

默认属性:hystrix.command.default.execution.isolation.thread.interruptOnTimeout

实例属性:hystrix.command.HystrixCommandKey.execution.isolation.thread.interruptOnTimeout

实例默认的设置:

HystrixCommandProperties.Setter()

.withExecutionIsolationThreadInterruptOnTimeout(boolean value)

execution.isolation.thread.interruptOnCancel

设置HystrixCommand.run()的执行但取消动作发生时候可以响应中断。

默认值:false

默认属性:hystrix.command.default.execution.isolation.thread.interruptOnCancel

实例属性:hystrix.command.HystrixCommandKey.execution.isolation.thread.interruptOnCancel

实例默认的设置:

HystrixCommandProperties.Setter()

.withExecutionIsolationThreadInterruptOnCancel(boolean value)

execution.isolation.semaphore.maxConcurrentRequests

设置当使用ExecutionIsolationStrategy.SEMAPHORE时,HystrixCommand.run()方法允许的最大请求数。如果达到最大并发数时,后续请求会被拒绝。

信号量应该是容器(比如Tomcat)线程池一小部分,不能等于或者略小于容器线程池大小,否则起不到保护作用。

默认值:10

默认属性:hystrix.command.default.execution.isolation.semaphore.maxConcurrentRequests

实例属性:hystrix.command.HystrixCommandKey.execution.isolation.semaphore.maxConcurrentRequests

实例默认的设置:

HystrixCommandProperties.Setter()

.withExecutionIsolationSemaphoreMaxConcurrentRequests(int value)

回退

下面的属性控制HystrixCommand.getFallback()执行。这些属性对ExecutionIsolationStrategy.THREAD和ExecutionIsolationStrategy.SEMAPHORE都有效。

fallback.isolation.semaphore.maxConcurrentRequests

设置调用线程产生的HystrixCommand.getFallback()方法的允许最大请求数目。

如果达到最大并发数目,后续请求将会被拒绝,如果没有实现回退,则抛出异常。

默认值:10

默认属性:hystrix.command.default.fallback.isolation.semaphore.maxConcurrentRequests

实例属性:hystrix.command.HystrixCommandKey.fallback.isolation.semaphore.maxConcurrentRequests

实例默认:

HystrixCommandProperties.Setter()

.withFallbackIsolationSemaphoreMaxConcurrentRequests(int value)

fallback.enabled

该属性决定当故障或者拒绝发生时,一个调用将会去尝试HystrixCommand.getFallback()。

默认值:true

默认属性:hystrix.command.default.fallback.enabled

实例属性:hystrix.command.HystrixCommandKey.fallback.enabled

实例默认的设置:HystrixCommandProperties.Setter()

.withFallbackEnabled(boolean value)

断路器(Circuit Breaker)

circuitBreaker.enabled

设置断路器是否起作用。

默认值:true

默认属性:hystrix.command.default.circuitBreaker.enabled

实例属性:hystrix.command.HystrixCommandKey.circuitBreaker.enabled

实例默认的设置:HystrixCommandProperties.Setter()

.withCircuitBreakerEnabled(boolean value)

circuitBreaker.requestVolumeThreshold

设置在一个滚动窗口中,打开断路器的最少请求数。

比如:如果值是20,在一个窗口内(比如10秒),收到19个请求,即使这19个请求都失败了,断路器也不会打开。

默认值:20

默认属性:hystrix.command.default.circuitBreaker.requestVolumeThreshold

实例属性:hystrix.command.HystrixCommandKey.circuitBreaker.requestVolumeThreshold

实例默认的设置:HystrixCommandProperties.Setter()

.withCircuitBreakerRequestVolumeThreshold(int value)

circuitBreaker.sleepWindowInMilliseconds

设置在回路被打开,拒绝请求到再次尝试请求并决定回路是否继续打开的时间。

默认值:5000(毫秒)

默认属性:hystrix.command.default.circuitBreaker.sleepWindowInMilliseconds

实例属性:hystrix.command.HystrixCommandKey.circuitBreaker.sleepWindowInMilliseconds

实例默认的设置:

HystrixCommandProperties.Setter()

.withCircuitBreakerSleepWindowInMilliseconds(int value)

circuitBreaker.errorThresholdPercentage

设置打开回路并启动回退逻辑的错误比率。

默认值:50

默认属性:hystrix.command.default.circuitBreaker.errorThresholdPercentage

实例属性:hystrix.command.HystrixCommandKey.circuitBreaker.errorThresholdPercentage

实例默认的设置:HystrixCommandProperties.Setter()

.withCircuitBreakerErrorThresholdPercentage(int value)

circuitBreaker.forceOpen

如果该属性设置为true,强制断路器进入打开状态,将会拒绝所有的请求。

该属性优先级比circuitBreaker.forceClosed高。

默认值:false

默认属性:hystrix.command.default.circuitBreaker.forceOpen

实例属性:hystrix.command.HystrixCommandKey.circuitBreaker.forceOpen

实例默认的设置:HystrixCommandProperties.Setter()

.withCircuitBreakerForceOpen(boolean value)

circuitBreaker.forceClosed

如果该属性设置为true,强制断路器进入关闭状态,将会允许所有的请求,无视错误率。

默认值:false

默认属性:hystrix.command.default.circuitBreaker.forceClosed

实例属性:hystrix.command.HystrixCommandKey.circuitBreaker.forceClosed

实例默认的设置:HystrixCommandProperties.Setter()

.withCircuitBreakerForceClosed(boolean value)

请求上下文

requestCache.enabled

设置HystrixCommand.getCacheKey()是否启用,由HystrixRequestCache通过请求缓存提供去重复数据功能。

默认值:true

默认属性:hystrix.command.default.requestCache.enabled

实例属性:hystrix.command.HystrixCommandKey.requestCache.enabled

实例默认的设置:HystrixCommandProperties.Setter()

.withRequestCacheEnabled(boolean value)

requestLog.enabled

设置HystrixCommand执行和事件是否要记录日志到HystrixRequestLog。

默认值:true

默认属性:hystrix.command.default.requestLog.enabled

实例属性:hystrix.command.HystrixCommandKey.requestLog.enabled

实例默认的设置:HystrixCommandProperties.Setter()

.withRequestLogEnabled(boolean value)

压缩器属性

下面的属性可以控制HystrixCollapser行为。

maxRequestsInBatch

设置触发批处理执行之前,在批处理中允许的最大请求数。

默认值:Integer.MAX_VALUE

默认属性:hystrix.collapser.default.maxRequestsInBatch

实例属性:hystrix.collapser.HystrixCollapserKey.maxRequestsInBatch

实例默认的设置:HystrixCollapserProperties.Setter()

.withMaxRequestsInBatch(int value)

timerDelayInMilliseconds

设置批处理创建到执行之间的毫秒数。

默认值:10

默认属性:hystrix.collapser.default.timerDelayInMilliseconds

实例属性:hystrix.collapser.HystrixCollapserKey.timerDelayInMilliseconds

Hystrix总结的更多相关文章

  1. 使用Hystrix提高系统可用性

    今天稍微复杂点的互联网应用,服务端基本都是分布式的,大量的服务支撑起整个系统,服务之间也难免有大量的依赖关系,依赖都是通过网络连接起来. (图片来源:https://github.com/Netfli ...

  2. Hystrix框架5--请求缓存和collapser

    简介 在Hystrix中有个Request的概念,有一些操作需要在request中进行 缓存 在Hystrix调用服务时,如果只是查询接口,可以使用缓存进行优化,从而跳过真实访问请求. 应用 需要启用 ...

  3. Hystrix框架4--circuit

    circuit 在Hystrix调用服务时,难免会遇到异常,如对方服务不可用,在这种情况下如果仍然不停地调用就是不必要的,在Hystrix中可以配置使用circuit,当达到一定程度错误,就会自动调用 ...

  4. Hystrix框架3--线程池

    线程池 在Hystrix中Command默认是运行在一个单独的线程池中的,线程池的名称是根据设定的ThreadPoolKey定义的,如果没有设置那么会使用CommandGroupKey作为线程池. 这 ...

  5. Hystrix框架2--超时

    timeout 在调用第三方服务时有些情况需要对服务响应时间进行把控,当超时的情况下进行fallback的处理 下面来看下超时的案例 public class CommandTimeout exten ...

  6. Hystrix框架1--入门

    介绍 在开发应用中或多或少会依赖各种外界的服务,利用各个服务来完成自己的业务需求,现在流行的微服务架构更是离不开各个服务之间的调用,这就导致整体应用的可用性依赖于各个依赖服务的可用性. 比如一个依赖3 ...

  7. Hystrix 使用与分析

    转载请注明出处哈:http://hot66hot.iteye.com/admin/blogs/2155036 一:为什么需要Hystrix? 在大中型分布式系统中,通常系统很多依赖(HTTP,hess ...

  8. Hystrix提高系统可用性

    使用Hystrix提高系统可用性 今天稍微复杂点的互联网应用,服务端基本都是分布式的,大量的服务支撑起整个系统,服务之间也难免有大量的依赖关系,依赖都是通过网络连接起来. (图片来源:https:// ...

  9. 为什么使用Hystrix?

    分布式服务弹性框架“Hystrix”实践与源码研究(一)   文章初衷 为了应对将来在线(特别是无线端)业务量的成倍增长,后端服务的分布式化程度需要不断提高,对于服务的延迟和容错管理将面临更大挑战,公 ...

  10. 分布式服务弹性框架“Hystrix”实践与源码研究(一)

    文章初衷 为了应对将来在线(特别是无线端)业务量的成倍增长,后端服务的分布式化程度需要不断提高,对于服务的延迟和容错管理将面临更大挑战,公司框架和开源团队选择内部推广Netflix的Hystrix,一 ...

随机推荐

  1. neo4j-jdbc driver

    https://github.com/neo4j-contrib/neo4j-jdbc/releases/tag/3.3.1

  2. 使用Redis分布式锁实现主备

    使用Redis分布式锁实现集群的主备 最近工作中遇到一个问题,我们会调用业务部门提供的HTTP接口获取所有的音视频任务信息,这些任务会被分发到各个机器节点进行处理.有两个方案: 方案一 为每台机器编号 ...

  3. Vue 全选/取消全选,反选/取消反选

    这是一个组件: <template> <div> <div> <input type="checkbox" v-model="i ...

  4. Orcle 查询语句

    首先,以超级管理员的身份登录oracle       sqlplus sys/bjsxt as sysdba   --然后,解除对scott用户的锁       alter user scott ac ...

  5. 循序渐进VUE+Element 前端应用开发(6)--- 常规Element 界面组件的使用

    在我们开发BS页面的时候,往往需要了解常规界面组件的使用,小到最普通的单文本输入框.多文本框.下拉列表,以及按钮.图片展示.弹出对话框.表单处理.条码二维码等等,本篇随笔基于普通表格业务的展示录入的场 ...

  6. Alpha冲刺 —— 5.1

    这个作业属于哪个课程 软件工程 这个作业要求在哪里 团队作业第五次--Alpha冲刺 这个作业的目标 Alpha冲刺 作业正文 正文 github链接 项目地址 其他参考文献 无 一.会议内容 1.展 ...

  7. Linux (三) 基础命令 上

    个人博客网:https://wushaopei.github.io/    (你想要这里多有) 一 . 背景知识 1. Linux系统中一切皆文件 在Linux系统中任何东西都是以文件形式来存储的.这 ...

  8. Vue中导出Excel表格方法

    本文记录一下在Vue中实现导出Excel表格的做法.参考度娘上各篇博客,最后实现功能 Excel表格,我的后端返回的是数据流,然后文件名是放进了content-disposition中,前端进行获取. ...

  9. Java实现简易计算器

    import java.util.Scanner; public class Demo_1 { public static void main(String[] args) { //输入的两个数字进行 ...

  10. Java实现 洛谷 P1170 兔八哥与猎人

    import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import ...