上一章我们讲了 Feign 开启断路器 Hystrix 的功能。由于 Feign 本身已经整合了 Ribbon 和 Hystrix 的部分功能,所以用起来比较简单。但是 Ribbon 中怎么使用 Hystrix 呢?本文将通过一个小 demo,教大家如何在使用 Ribbon 中加入 Hystrix 的功能。
Hystrix 提供了一个基于命令模式 HystrixCommand 来包装依赖调用逻辑,其每个命令在单独线程中或信号授权下执行。(Command 是在 Receiver 和 Invoker 之间添加的中间层,Command 实现了对 Receiver 的封装)。Hystrix 支持两种隔离策略:线程池隔离和信号量隔离(都是限制对共享资源的并发访问量)。
- ThreadPool:根据配置把不同命令分配到不同的线程池中,这是比较常用的隔离策略,其优点是隔离性好,并且可以配置断路某个依赖被设置断路之后,系统不会再尝试新起线程运行它,而是直接提示失败,或返回 fallback 值它的缺点是新起线程执行命令,在执行时必然涉及上下文的切换,这会造成一定的性能消耗但是 Netflix 做过实验,这种消耗对比其带来的价值是完全可以接受的,具体的数据参见 Hystrix-Wiki。
- Semaphores:顾名思义就是使用一个信号量来做隔离,开发者可以限制系统对某一个依赖的最高并发数,这个基本上就是一个限流的策略。每次调用依赖时都会检查一下是否到达信号量的限制值,如达到,则拒绝该策略的优点是不新起线程执行命令,减少上下文切换,缺点是无法配置断路,每次都一定会去尝试获取信号量。
为了简单,我们直接对之前的案例中的 xttblog-cloud-ribbon 项目进行一下整改。当然为了不污染之前的项目案例,我们还是新建一个工程:xttblog-ribbon-hystrix。pom.xml 的配置是一样的,我就略过了。application.yml 中,只改了一下端口和服务名称:
server: port: 7081 eureka: instance: hostname: localhost client: serviceUrl: defaultZone: http://${eureka.instance.hostname}:8761/eureka/ spring: application: name: xttblog-ribbon-hystrix
Springboot 入口类中,需要配置 @EnableCircuitBreaker 注解:
@SpringBootApplication @EnableDiscoveryClient //开启断路器功能 @EnableCircuitBreaker public class RibbonHystrixApplication { //开启软均衡负载 @LoadBalanced @Bean RestTemplate restTemplate() { return new RestTemplate(); } public static void main(String[] args) { SpringApplication.run(RibbonHystrixApplication.class, args); } }
RibbonController 和 CalService 保持不变,CalServiceImpl 的改动如下:
@Service public class CalServiceImpl implements CalService { @Autowired private RestTemplate restTemplate; @Autowired private LoadBalancerClient loadBalancerClient; @Override //指定断路后的回调方法(回调方法必须与原方法参数类型相同、返回值类型相同、方法名可以不同) @HystrixCommand(fallbackMethod="hystrixFallback") public Integer add(Integer a, Integer b) { String reqURL = "http://com.xttblog-cloud-producer/cal/add?a=" + a + "&b=" + b; test(); return restTemplate.getForEntity(reqURL, Integer.class).getBody(); } public Integer hystrixFallback(Integer a, Integer b){ System.out.println("服务熔断了。。。。"); return -1024; } private void test(){ ServiceInstance serviceInstance = loadBalancerClient.choose("com.xttblog-cloud-producer"); System.out.println("Host:" + serviceInstance.getHost() + ",ServiceId:" + serviceInstance.getServiceId() + ",Port:" + serviceInstance.getPort()); } }
使用 @HystrixCommand(fallbackMethod="hystrixFallback") 指定断路后,要执行的方法即可。
做完以上的代码编写,我们就可以依次启动 xttblog-eureka-server、xttblog-cloud-producer、xttblog-ribbon-hystrix 三个项目。然后在浏览器里输入 http://localhost:7081/test?a=1&b=10 进行访问,没有问题后,我们关闭掉 xttblog-cloud-producer 服务,再次刷新浏览器,返回结果中若有“-1024”,则说明成功的进行了熔断。
Hystrix 的配置参数
Hystrix 的大部分配置都是 hystrix.command.[HystrixCommandKey] 开头
其中 [HystrixCommandKey] 是可变的,默认是 default,即:hystrix.command.default(对于 Zuul 而言,CommandKey 就是 service id)
它常见的有以下几个配置
-
hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds
用来设置 thread 和 semaphore 两种隔离策略的超时时间,默认值是1000
建议设置这个参数,在 Hystrix-1.4.0 之前,semaphore-isolated 隔离策略是不能超时的,1.4.0 开始 semaphore-isolated 也支持超时时间了 -
hystrix.command.default.execution.isolation.semaphore.maxConcurrentRequests
此值并非 TPS、QPS、RPS 等都是相对值,它指的是 1 秒时间窗口内的事务 / 查询 / 请求,它是一个绝对值,无时间窗口
相当于亚毫秒级的,指任意时间点允许的并发数,当请求达到或超过该设置值后,其其余就会被拒绝,默认值是100 -
hystrix.command.default.execution.timeout.enabled
是否开启超时,默认为true -
hystrix.command.default.execution.isolation.thread.interruptOnTimeout
发生超时是是否中断线程,默认是true -
hystrix.command.default.execution.isolation.thread.interruptOnCancel
取消时是否中断线程,默认是false -
hystrix.command.default.circuitBreaker.requestVolumeThreshold
当在配置时间窗口内达到此数量的失败后,进行短路,默认20个 -
hystrix.command.default.circuitBreaker.sleepWindowInMilliseconds
短路多久以后开始尝试是否恢复,默认5s -
hystrix.command.default.circuitBreaker.errorThresholdPercentage
出错百分比阈值,当达到此阈值后,开始短路,默认50% -
hystrix.command.default.fallback.isolation.semaphore.maxConcurrentRequests
调用线程允许请求 HystrixCommand.GetFallback() 的最大数量,默认10,超出时将会有异常抛出
注意:该项配置对于 thread 隔离模式也起作用
以上就是列举的一些常见配置,更多内容可参考:https://github.com/Netflix/Hystrix/wiki/Configuration
本文源码已共享至:https://github.com/xmt1139057136/xttblog-cloud
: » Spring Cloud 教程第九章 Ribbon 整合断路器 Hystrix
原创文章,作者:bd101bd101,如若转载,请注明出处:https://blog.ytso.com/251828.html