1)Hystrix 线程池打满再来请求服务降级和熔断
2)hystrix 某个时间窗口内的buket时间内服务请求书和错误率导致降级和熔断
3)hystrix 滑动窗口配置,影响熔断以及熔断状态切换时间
4)hystrix 熔断状态切换(CLOSE,OPNE,HALF_OPEN)
5)hystrix.stream 或者Hystrix Dashboard 使用
PS: HystrixDashboard只是为了展示和验证,看代码时因为不熟悉RxJava的,滑动窗口统计部分可能看起来比较费力,可以通过这里仪表盘验证自己的想法和预测。
在使用Feign的场景下,一次远程调用经历了入戏图中几个组件,每个组件有自己的配置,比如超时时间,线程池数量,方法耗时。
这几个组件的一些配置可能会使得Hystrix触发降级和熔断【比如超时和线程池满了,以及业务异常】,所以有必要对上面的相关因素做一些了解,否则实验过程中会出现一些出乎意外的结果。
不做无准备之仗,再次之前先要对Hystrix的执行流程要有个清晰的认识,前面也看到,有feign,ribbon这两个组件,去掉之后还有rxjava语法,我在看的时候遇到很多不懂的地方这里将总结的流程发出来。
图中大致可以看到几个核心的逻辑:
Hystrix判断是否熔断打开 一个bucket时间内请求数达到阈值,并且错误率达到阈值----> 熔断打开一个bucket时间内请求数未达到阈值 ----> 熔断不打开 【即便是错误率100%】 Hystrix 熔断状态切换Hystrix 执行结果汇入滑动窗口还能得出一些逻辑:
熔断直接进入降级逻辑降级不一定是熔断状态熔断是在达到熔断指标之后下一次请求进入的时候判断得出的统计结果跟时间窗口每个bucket存储的各项数据指标有关系一个很普通的Controller,以服务提供者角色对外提供服务
@Slf4j @RestController @RequestMapping("/user") public class UserResource implements UserServiceFeignApi { private Random random = new Random(); /** * @description 模拟服务提供方方法耗时很长,主要是位让hystrix线程池打满,看看线程池慢之后降级,熔断 * @author yzMa * @date 2019/8/6 * @param * @return */ @GetMapping("/get/{id}") @Override public UserModel getById(@PathVariable Long id) throws InterruptedException { int nextVal = 600000; //random.nextInt(10000); log.info("sleep time ={}",nextVal); Thread.sleep(nextVal); UserModel userModel = new UserModel(); userModel.setId(id); userModel.setName("myz"+nextVal); return userModel; } /** * @description 模拟方法抛出异常,快速返回,以及随机业务耗时 * @author yzMa * @date 2019/11/1 * @param * @return */ @GetMapping("/hi/{name}") @Override public String sayHi(@PathVariable(name = "name") String name, @RequestParam(name = "fast",defaultValue = "false") boolean fast, @RequestParam(name = "throwEx",defaultValue = "false") boolean throwEx) throws InterruptedException { String val = "hi,"+name; if(throwEx){ throw new RuntimeException("服务端异常"); } if(fast){ return val; } int waitTime = random.nextInt(2000); log.info("wait time {} ms",waitTime); Thread.sleep(waitTime); return val; } }两个方法在演示中的作用:
UserServiceFeignApi#getById(Long) 模拟服务提供方方法耗时很长,主要是位让hystrix线程池打满,看看线程池慢之后降级,熔断 UserServiceFeignApi#sayHi(String,boolean,boolean); 模拟服务提供方方法抛出异常,快速返回,以及随机业务耗时服务方提供的接口,翻遍消费方调用,可以直接被消费方扫描,就像执行本地接口方法
代码依然很简单,直接调用feign接口。
降级逻辑也很简单
配置相关含义介绍
HystrixCommand的goupKey ,在Feign表现为serviceId=sc-user ,该serviceId表示的类以及类的所有方法公用一个线程池,来执行远程调用。hystrix线程池属于应用级别 HystrixCommand的CommandKey,在Feign表现为Feign接口的方法比如UserServiceFeignApi#sayHi(String,boolean,boolean)有自己独立的配置 隔离策略超时时间熔断器配置 滑动窗口的时长滑动窗口的buket的数量,因此可以推导出有一个窗口有多少个buket,再结合定时任务移动一个bucket就能统计出每个bucket的指标信息决定是否要熔断 hystrix 隔离策略,熔断配置,线程池的future超时属于方法级别 Hystrix 默认没有指定特定的commandKey的时候使用默认commandKey=default hystrix 默认配置我们用jmeter来发送请求,线程数跟Hystrix线程池数量一样,
Future超时时间 URL超时时间 提供方接口耗时都很长 这样一来运行Jmeter的时候线程池就全部打满,并被hold住,再次在浏览器发送请求。
测试方法为UserServiceFeignApi#getById(Long) 如下的特征:
方法耗时时间可以sleep时间长一些
hystrix的线程池Future的超时时间大于Feign(即URL的超时时间)
Feign的超时时间大于方法耗时
Feign中设置的超时时间最终设置的是上图的http部分,默认是java.net.URL的超时时间
feign: hystrix: enabled: true # 该版本需要手工启用 client: config: sc-user: # 在客户端配置的服务提供方 配置信息的key readTimeout: 400000 #4000 Url的超时时间 connectTimeout: 20000受篇幅影响 Rxjava的滑动窗口部分可以到这里查看,这里的rxjava部分完全是从Hystrix中抽离出来的