Hystrix总结
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总结的更多相关文章
- 使用Hystrix提高系统可用性
今天稍微复杂点的互联网应用,服务端基本都是分布式的,大量的服务支撑起整个系统,服务之间也难免有大量的依赖关系,依赖都是通过网络连接起来. (图片来源:https://github.com/Netfli ...
- Hystrix框架5--请求缓存和collapser
简介 在Hystrix中有个Request的概念,有一些操作需要在request中进行 缓存 在Hystrix调用服务时,如果只是查询接口,可以使用缓存进行优化,从而跳过真实访问请求. 应用 需要启用 ...
- Hystrix框架4--circuit
circuit 在Hystrix调用服务时,难免会遇到异常,如对方服务不可用,在这种情况下如果仍然不停地调用就是不必要的,在Hystrix中可以配置使用circuit,当达到一定程度错误,就会自动调用 ...
- Hystrix框架3--线程池
线程池 在Hystrix中Command默认是运行在一个单独的线程池中的,线程池的名称是根据设定的ThreadPoolKey定义的,如果没有设置那么会使用CommandGroupKey作为线程池. 这 ...
- Hystrix框架2--超时
timeout 在调用第三方服务时有些情况需要对服务响应时间进行把控,当超时的情况下进行fallback的处理 下面来看下超时的案例 public class CommandTimeout exten ...
- Hystrix框架1--入门
介绍 在开发应用中或多或少会依赖各种外界的服务,利用各个服务来完成自己的业务需求,现在流行的微服务架构更是离不开各个服务之间的调用,这就导致整体应用的可用性依赖于各个依赖服务的可用性. 比如一个依赖3 ...
- Hystrix 使用与分析
转载请注明出处哈:http://hot66hot.iteye.com/admin/blogs/2155036 一:为什么需要Hystrix? 在大中型分布式系统中,通常系统很多依赖(HTTP,hess ...
- Hystrix提高系统可用性
使用Hystrix提高系统可用性 今天稍微复杂点的互联网应用,服务端基本都是分布式的,大量的服务支撑起整个系统,服务之间也难免有大量的依赖关系,依赖都是通过网络连接起来. (图片来源:https:// ...
- 为什么使用Hystrix?
分布式服务弹性框架“Hystrix”实践与源码研究(一) 文章初衷 为了应对将来在线(特别是无线端)业务量的成倍增长,后端服务的分布式化程度需要不断提高,对于服务的延迟和容错管理将面临更大挑战,公 ...
- 分布式服务弹性框架“Hystrix”实践与源码研究(一)
文章初衷 为了应对将来在线(特别是无线端)业务量的成倍增长,后端服务的分布式化程度需要不断提高,对于服务的延迟和容错管理将面临更大挑战,公司框架和开源团队选择内部推广Netflix的Hystrix,一 ...
随机推荐
- [工具推荐]004.EXE签名工具SignTool使用教程
数字证书,真是个神奇的东西,可以保证软件不被修改,可以表明文件的发布日期,最重要的,可以很大程度的减少杀毒软件的误报,当然,这就要使用可信任的机构颁发的证书了. 现在要说的不是申请证书,而是如何制作自 ...
- 一个 static 还能难得住我?
static 是我们日常生活中经常用到的关键字,也是 Java 中非常重要的一个关键字,static 可以修饰变量.方法.做静态代码块.静态导包等,下面我们就来具体聊一聊这个关键字,我们先从基础开始, ...
- 我天!xx.equals(null) 是什么骚操作??
问题背景 我的天,最近做 Code Review 看到一个同事的骚操作,他写了一个工具类,大概是这样的: public static boolean isNull(Object object){ re ...
- oracle11g数据库导入、导出操作
一.在linux系统中导入数据库. 1.linux中先输入 su - oracle下切换到oracle用户.然后以sysdba打开sqlplus:sqlplus / as sysdba 然后创建表空间 ...
- call 和 apply 的区别?哪个性能更好?
1.call 和 apply 都是 function 类 原型上的方法:每一个函数作为 function 的实例都能调用这两个方法:这两个方法执行的目的都是用来改变函数中 this 指向的,让函数执行 ...
- 【Linux】CentOS7中使用mysql,查询结果显示中文乱码的解决办法
1.登录mysql mysql -u root -p 2.查看mysql字符集 mysql> show variables like 'chara%'; mysql> show varia ...
- CVE-2020-0796永恒之黑复现POC EXP以及修复方案
描述: 北京时间3月12日,针对最新披露的SMB远程代码执行漏洞(CVE-2020-0796),微软官方发布了针对Windows 10/Server禁用SMBv3(SMB 3.1.1版本)协议压缩的安 ...
- Java实现 LeetCode 599 两个列表的最小索引总和(使用hash提高效率)
599. 两个列表的最小索引总和 假设Andy和Doris想在晚餐时选择一家餐厅,并且他们都有一个表示最喜爱餐厅的列表,每个餐厅的名字用字符串表示. 你需要帮助他们用最少的索引和找出他们共同喜爱的餐厅 ...
- Java实现 LeetCode 239 滑动窗口最大值
239. 滑动窗口最大值 给定一个数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧.你只可以看到在滑动窗口内的 k 个数字.滑动窗口每次只向右移动一位. 返回滑动窗口中的最 ...
- lambda表达式操作DataTable
using System;using System.Collections.Generic;using System.Data;using System.Linq;using System.Text; ...