SpringCloud(三)之我学 Hystrix
1、断路器
在消费服务的启动类,添加注解:@EnableCircuitBreaker,在消费服务的调用类上,添加注解:@HystrixCommand(fallbackMethod = "") -> 失败了调的方法。(熔断超时默认 2s )
当被调用的服务,超时或者未反应/down掉,就会触发熔断请求,返回定义的逻辑。
工作流程:
1)、加注解:@HystrixCommand 或 @HystrixObservableCommand ,前者用于依赖的服务返回单个操作结果的时候,后者用于依赖的服务返回多个操作结果的时候。(具体的实现看书籍)
命令模式,将客户端请求封装为一个对象,能让不同的请求对客户端进行参数化。(让不同类型的参数,都可以请求)
2)、命令执行:
HystrixCommand 实现了 execute()、queue() 执行方法。
execute():同步执行,从依赖的服务返回一个单一的结果对象,或错误时抛出异常,R value = command.execute();
queue():异步执行,直接返回一个 Future 对象,其中包含了服务执行结束时返回的单一结果对象,Future<R> fValue = command.queue();
HystrixObservableCommand 实现了 observe()、toObservable() 执行方法。
Observable<R> obValue = command.observe(),代表操作了多个结果,返回 HotObservanle;
Observable<R> ocValue = command.toObservable(),也代表操作了多个结果,返回 Cold Observable;
Hystrix 底层实现了大量的 RxJava,RxJava 的观察者-订阅者模式。
Observable 向订阅者 Subscriber 对象发布事件(即异服务调用),一个Observable 可以发出多个事件,直到结束或者发生异常。每发出一个事件,就会调用对应观察者 Subscriber.onNext() 方法。最后一定会调用 Subscriber.onCompleted() 或者 Subscriber.onError() 结束该时间的操作流。
3)、结果是否被缓存:当命令的请求缓存功能开启,命令缓存命中,缓存的结果就会以 Observable 对象的形式返回。
4)、断路器是否打开: - 断路器是否已经开始运行
命令结果没有命中缓存中,如果断路器打开,Hystrix 不会执行命令,而是转到 fallback 处理逻辑。如果断路器关闭,则继续执行。
5)、线程池/请求队列/信号量是否占满: - 线程太多
如果与命令相关的线程池或请求队列或者信号量已经占满,则 Hystrix 也不会执行命令,而是转接到 fallback 处理逻辑。
该线程池并非容易的线程池,而是每个依赖服务的专有线程池。
6)、请求依赖服务:
HystrixObserveableCommand.construct() 或 HystrixCommand.run(),决定了采取什么样的方式去请求依赖服务。
第一种返回一个 Observable 对象来发射多个结果,或通过 onError 发送错误通知;
第二种返回一个单一的结果,或者抛出异常。
超时也会转到 fallback 处理逻辑。
7)、计算断路器的健康度: - 服务调用失败/超时等超过设置
Hystrix 会将成功、失败、拒绝、超时等信息报告给断路器,断路器会维护一组计数器来统计这些数据。根据数据值,来对某个依赖服务的请求进行 "熔断/短路",直到恢复期结束。在恢复期结束后,再根据统计数据判断是否还是未达到健康指标,或再次"熔断/短路"。
8)、fallback 处理:- 回退 - 服务降级
当命令执行失败的时候,Hystrix 会进入 fallback 尝试回退处理,该操作叫做 "服务降级"。
第4、5、6步都可能会引起服务降级。
最终的降级逻辑一定不是一个依赖网络请求的处理,而是一个能够稳定返回结果的处理逻辑。
HystrixCommand.getFallback() 来实现服务降级;
HystrixObservableCommand.resumeWithFallback() 来实现降级逻辑。
9)、返回成功的响应:
2、断路器原理
HystrixCricuitBreaker 接口:
allowRequest:每个 hystrix 命令的请求都通过它判断是否被执行;
isOpen:返回当前断路器是否打开;
markSuccess():用来闭合断路器,并重置度量指标对象。
HystrixCricuitBreakImpl 是实现类,有几个重要核心对象,一个是 HystrixCommand 实例的属性对象,一个是记录各个度量指标的对象,一个是断路器是否打开的标志,一个是断路器打开或上一次测试的时间戳。
断路器从关闭到打开(默认时间窗10s的请求信息快照):
1)、请求总数 QPS 在预设的阈值范围内就返回 false,表示断路器还是关闭。阈值默认值20。
2)、错误百分比在阈值范围内就返回 false,表示断路器还是关闭。默认是50。
3)、以上两个条件都不满足,断路器就设置为打开状态(熔断/短路)。如果是从关闭状态切到打开状态,就将当前时间记录到上面的时间戳对象中。
allowSingleTest() 为断路器再设置一个休眠时间(默认5s),在该休眠时间达到只有,再次允许请求尝试访问。若请求再次失败,断路器又进入打开状态。请求成功,则是关闭状态。
所以 allowSingleTest() 与 isOpen() 方法的配合,实现了断路器的打开和关闭状态的切换。
3、依赖隔离
会为每个依赖服务创建一个独立的线程池,这样就算某个依赖服务出现问题后,也只对该依赖服务的调用产生影响,不影响其他依赖服务。
特点:
依赖的服务从失效恢复正常后,它的线程池会被清理并且能够马上恢复健康服务。容器级别的清理 恢复速度慢的多;
当依赖的服务出现配置错误的时候,线程池会被快速反映出此问题(失败、延迟、超时、拒绝等增加情况)。
线程池的开销在设计的时候做过实验,消耗相对于来说是微乎其微的。对于某些需求来说,如果该消耗觉得很大,又用了信号量来优化。
信号量控制单个依赖服务的并发量,但是不能设置超时和实现异步访问。线程池和信号量可以切换。
在降级逻辑,Hystrix 尝试降级逻辑时,会在调用线程中使用信号量。或者命令执行。
4、使用详解
1)、创建请求命令
可以用继承 HystrixCommand 或者 @HystrixCommand 来实现熔断,注解添加在异服务之间调用的接口上。
并且该注解可以实现 同步/异步 的操作。异步用 Future<T> 接收返回参数。
2)、定义服务降级
fallback 是 Hystrix 命令执行失败后使用的后备办法,实现服务的降级处理逻辑。
继承方式的话,用重载 getFallback() 方法来实现降级处理;
注解方式 @HystrixCommand(fallbackMethod = "failMethod") ,定义一个 faliMethod 方法,作为降级处理。(在同一个类中)
3)、异常处理
当服务调用发生异常,除了 HystrixBadRequestException 之外,其他异常都会被 Hystrix 认为命令执行失败,并触发服务降级的处理逻辑。
使用注解 @HystrixCommand(ignoreExceptions = {XXException.class}) 可以忽略指定异常类型。当遇到该类型的异常时,就会被包装 HystrixBadRequestException 异常抛出,而不会触发降级的处理逻辑。
4)、异常获取
异常获取到后,可以根据不同的异常判断,做出不同的处理方式。直接在 fallback() 方法里定义一个 Throwable e ,就可以获取触发降级的具体异常内容。(e.getMessage())
5)、命令名称、分组以及线程池划分
Hystrix 会让相同组名的命令使用同一个线程池。所以创建 Hystrix 命令时,为其制定命令组名来实现默认的线程池划分。(还提供了 HystrixThreadPoolKey 来对线程池进行设置,进行更加细粒度的线程池划分,实际情况通常使用这一种划分方式)
注解方式实现:@HystrixCommand(commandKey="getUserById",groupKey="UserGroup",ThreadPoolKey="getUserByIdThread")
6)、请求缓存
开启请求缓存功能:继承方式,重载 getCacheKey() 方式来开启请求缓存。
好处:
减少重复请求数,降低依赖服务的并发度(降低压力);
在同一用户请求的上下文中,相同依赖服务的返回数据一致;
请求缓存在 run() 和 construct() 执行之前生效,可以减少不必要的线程开销;
清理失效缓存功能:通过 HystrixRequestCache.clear() 方法来进行缓存的清理,在做更新操作时,就将缓存清理掉。
注解方式:@CacheResult 标记请求命令返回的结果应该被缓存,必须和 @HystrixCommand 结合使用;
@CacheRemove 让请求命令的缓存失效,失效的缓存是根据 key 来的。(commandKey)
@CacheKey 给参数添加标记,使之成为缓存的 key。
7)、请求合并
远程调用最常见的问题就是 通信消耗和连接总数。Hystrix 提供了 HystrixCollapser 来实现请求的合并,以减少通信消耗和线程池的占用。
HystrixCollapser 实现了 在 @HystrixCommand 之前放置了一个合并处理器,将处于一个很短时间内(默认10ms)对同一依赖服务的多个请求进行整合并以批量方式发起请求。
SpringCloud(三)之我学 Hystrix的更多相关文章
- 玩转SpringCloud(F版本) 三.断路器(Hystrix)RestTemplate+Ribbon和Feign两种方式
此文章基于: 玩转SpringCloud 一.服务的注册与发现(Eureka) 玩转SpringCloud 二.服务消费者(1)ribbon+restTemplate 转SpringCloud 二.服 ...
- SpringCloud 在Feign上使用Hystrix(断路由)
SpringCloud 在Feign上使用Hystrix(断路由) 第一步:由于Feign的起步依赖中已经引入了Hystrix的依赖,所以只需要开启Hystrix的功能,在properties文件中 ...
- 三个层面学playbook(核心)
三个层面学playbook(核心) ansible-playbook是ansible工具中的核心,对比ad-hoc(ansible)命令,可以把playbook理解为一系列动作的组成,结果传递.判断等 ...
- SpringCloud学习笔记(5):Hystrix Dashboard可视化监控数据
简介 上篇文章中讲了使用Hystrix实现容错,除此之外,Hystrix还提供了近乎实时的监控.本文将介绍如何进行服务监控以及使用Hystrix Dashboard来让监控数据图形化. 项目介绍 sc ...
- springcloud费话之断路器(hystrix in feign)
目录: springcloud费话之Eureka基础 springcloud费话之Eureka集群 springcloud费话之Eureka服务访问(restTemplate) springcloud ...
- 每天学点SpringCloud(十一):Hystrix仪表盘
在SpringCloud学习系列博客第六篇文章中,我们已经学习了Hystrix的使用,但是那篇文章中有一点遗漏没有讲,那就是Hystrix Dashboard ,它可以实时的监控Hystrix的运行情 ...
- 每天学点SpringCloud(六):Hystrix使用
Hystrix是一个实现断路器模式的库.什么是断路器模式呢?就像我们家庭中的电闸一样,如果有那一处出现意外,那么电闸就会立刻跳闸来防止因为这一处意外而引起更大的事故,直到我们确认处理完那一处意外后才可 ...
- SpringCloud学习系列之三----- 断路器(Hystrix)和断路器监控(Dashboard)
前言 本篇主要介绍的是SpringCloud中的断路器(Hystrix)和断路器指标看板(Dashboard)的相关使用知识. SpringCloud Hystrix Hystrix 介绍 Netfl ...
- SpringCloud IDEA 教学 (四) 断路器(Hystrix)
写在开始 在SpringCloud项目中,服务之间相互调用(RPC Remote Procedure Call —远程过程调用),处于调用链路底层的服务产生不可用情况时,请求会产生堆积使得服务器线程阻 ...
随机推荐
- C++ 随机函数/伪随机函数
使用rand()函数时,每次随机数都是固定(伪随机数),在前面加上以下函数,每次生成的随机数为随机, srand((int)time(NULL)); rand();
- C#的关键字Explicit 和 Implicit
一.explicit和implicit explicit 关键字用于声明必须使用强制转换来调用的用户定义的类型转换运算符:implicit 关键字用于声明隐式的用户自定义的类型转换运算符. 总结来说: ...
- isEmpty 判空函数 内部分别判断是 null 空数组 等
import { oneOf, isEmpty } from '@/libs/tools' export const isEmpty = (value) => { if (value == nu ...
- 【Weiss】【第03章】练习3.9:大整数运算包
[练习3.9] 编写任意精度的整数运算包,要求使用类似多项式运算的方法.计算24000内数字0到9的分布.
- Linux学习第六天
学习Linux环境下的挂载命令. 什么是挂载命令? 1.Windows下,mount挂载,就是给磁盘分区提供一个盘符(C,D,E,...).比如插入U盘后系统自动分配给了它I:盘符其实就是挂载,退优盘 ...
- Natas30 Writeup(sql注入)
Natas30: 本关是一个登录页面,查看源码,可以发现关键代码. if ('POST' eq request_method && param('username') &&am ...
- git常用命令学习配详细说明
原文链接 把当前目录变成Git可以管理的仓库 git init 查看仓库当前的状态 git status 添加新/变动文件 git add <文件名> // 添加某个新文件(目录) git ...
- 【攻防世界】simple-unpack
知识:upx脱壳 simple-unpack 难度系数: 3.0 题目来源: 暂无 题目描述:菜鸡拿到了一个被加壳的二进制文件 提示说有壳子:然后用PE分析发现是ELF upx的壳子
- Docker Data
docker data 六.Docker存储 docker存储驱动storage driver(优先使用linux默认的storage driver,因为比较稳定) ubuntu:aufs,/var/ ...
- Java——Collection集合
##Collection集合 1.Collection集合是单列集合 2.Collection是所有单列集合最顶层的接口,定义了所有单列集合的共性方法 任意的单列集合都可以使用Collection接口 ...