一、简介
-
基本介绍
在微服务架构中,我们将服务拆分成若干个单元,通过远程服务互相调用,如果多级节点调用过程中一个节点出现故障,就会因依赖关系形成故障蔓延,导致雪崩,为了保证系统的可用我们提出了断路器模型。Netflix开源了Hystrix组件,这在2.4.X以上版本使用的是Resilience4j(这是一款轻量级,易于使用的容错库,其灵感来自于Netflix Hystrix,但是专为Java8和函数式编程而设计)
-
为什么断路
- 隔离:将请求封装在HystrixCommand中,然后这些请求在一个独立的线程中执行,每个依赖服务维护一个小的线程池(或信号量),在调用失败或超时的情况下可以断开依赖调用或者返回指定逻辑
- 降级:服务降级是指当请求后端服务出现异常的时候, 可以使用fallback方法返回的值
- 熔断:当HystrixCommand请求后端服务失败数量超过一定比例(默认50%), 断路器会切换到开路状态(Open). 这时所有请求会直接失败而不会发送到后端服务,断路器保持在开路状态一段时间后(默认5秒),自动切换到半开路状态(HALF-OPEN),这时会判断下一次请求的返回情况, 如果请求成功, 断路器切回闭路状态(CLOSED),否则重新切换到开路状态(OPEN)
- 仪表盘:Hystrix提供了可视化的仪表盘,对服务可用性做到实时监测的作用
-
Hystrix流程说明
1:每次调用创建一个新的HystrixCommand,把依赖调用封装在run()方法中.
2:执行execute()/queue做同步或异步调用.
4:判断熔断器(circuit-breaker)是否打开,如果打开跳到步骤8,进行降级策略,如果关闭进入步骤5.
5:判断线程池/队列/信号量是否跑满,如果跑满进入降级步骤8,否则继续后续步骤6.
6:调用HystrixCommand的run方法.运行依赖逻辑
6a:依赖逻辑调用超时,进入步骤8.
7:判断逻辑是否调用成功
7a:返回成功调用结果
7b:调用出错,进入步骤8.
8:计算熔断器状态,所有的运行状态(成功, 失败, 拒绝,超时)上报给熔断器,用于统计从而判断熔断器状态.
9:getFallback()降级逻辑.以下四种情况将触发getFallback调用:
(1):run()方法抛出非HystrixBadRequestException异常。
(2):run()方法调用超时
(3):熔断器开启拦截调用
(4):线程池/队列/信号量是否跑满
9a:没有实现getFallback的Command将直接抛出异常
9b:fallback降级逻辑调用成功直接返回
9c:降级逻辑调用失败抛出异常
10:返回执行成功结果 -
断路策略
-
主动断开:在客户端请求时,直接设置超时时间,超过时间直接返回,不要造成服务堆积
-
限流:在高并发场景下,设置最大并发数
-
降级:服务失败或异常后,返回指定默认信息,这个一般是在服务端处理
-
熔断:当错误数超过阈值时快速失败,不调用后端服务,同时隔一定时间放几个请求去重试后端服务是否能正常调用,如果成功则关闭熔断状态,失败则继续快速失败,直接返回。(此处有个重试,重试就是弹性恢复的能力)
-
隔离:把每个依赖或调用的服务都隔离开来,防止级联失败引起整体服务不可用
-
二、Hystrix独立使用
-
pom依赖
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-hystrix</artifactId> </dependency> <!-- 仪表盘依赖 --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId> </dependency> <!-- 健康监控包 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> 复制代码
-
启动配置
@SpringBootApplication @EnableDiscoveryClient @EnableCircuitBreaker//开启断路器 @EnableHystrixDashboard//开启仪表盘 public class BikeHystrixApplication { public static void main(String[] args) { SpringApplication.run(BikeHystrixApplication.class, args); } /** * 设置负载均衡 * @return */ @Bean @LoadBalanced RestTemplate restTemplate(){ return new RestTemplate(); } } 复制代码
-
测试验证
-
服务降级:一般是服务端的断路策略,当服务不可用时,返回一个默认值。
@RestController @RequestMapping("/bike-hystrix") @Slf4j public class BikeHystrixController { @Autowired RestTemplate restTemplate; //添加注解,指定回调方法 @HystrixCommand(fallbackMethod = "fallBack") @GetMapping("/hystrix") public String hystrix(){ //模拟服务异常,触发服务降级 int i=1/0; String resp = null; /** * 如果restTemplate没有设置@LoadBalanced是不能用服务名代替ip:port的方式请求,否则会报识别不了host的错误, * 如果配置了该注解,那么就需要使用服务名 */ resp = restTemplate.getForObject("http://bike-business/bike-business/hystrix", String.class); return resp; } //当业务方法执行异常时会执行该方法,相当于是服务的降级,对于服务降级常用于服务端。当当前服务不可用时返回一个默认值 public String fallBack(){ return "this is hystrix err "; } } 复制代码
HystrixCommand注解说明
@Target({ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @Inherited @Documented public @interface HystrixCommand { // HystrixCommand 命令所属的组的名称:默认注解方法类的名称 String groupKey() default ""; // HystrixCommand 命令的key值,默认值为注解方法的名称 String commandKey() default ""; // 线程池名称,默认定义为groupKey String threadPoolKey() default ""; // 定义回退方法的名称, 此方法必须和hystrix的执行方法在相同类中 String fallbackMethod() default ""; // 配置hystrix命令的参数 HystrixProperty[] commandProperties() default {}; // 配置hystrix依赖的线程池的参数 HystrixProperty[] threadPoolProperties() default {}; // 如果hystrix方法抛出的异常包括RUNTIME_EXCEPTION,则会被封装HystrixRuntimeException异常。我们也可以通过此方法定义哪些需要忽略的异常 Class<? extends Throwable>[] ignoreExceptions() default {}; // 定义执行hystrix observable的命令的模式,类型详细见ObservableExecutionMode ObservableExecutionMode observableExecutionMode() default ObservableExecutionMode.EAGER; // 如果hystrix方法抛出的异常包括RUNTIME_EXCEPTION,则会被封装HystrixRuntimeException异常。此方法定义需要抛出的异常 HystrixException[] raiseHystrixExceptions() default {}; // 定义回调方法:但是defaultFallback不能传入参数,返回参数和hystrix的命令兼容 String defaultFallback() default ""; } 复制代码
-
服务熔断
-
我们测试服务熔断需要开启多个服务节点来验证,分别开启bike-business,bike-business2两个业务系统,添加相同的接口
@GetMapping("/hystrix") public String hystrix(){ return "hystrix resp : " + port; } 复制代码
-
客户端添加hystrix超时时间,超时设置了2秒,我们在上一步bike-business2系统关闭模拟服务器宕机,那么根据ribbon的负载均衡策略,在多次轮训到bike-business2业务系统时,监测到服务器宕机,就会触发熔断机制。那么我们可以预想,当bike-business2熔断之后,结果只会返回bike-business的结果
hystrix: command: default: execution: isolation: strategy: SEMAPHORE thread: timeoutInMilliseconds: 2000 # 设置hystrix的超时时间为2s 复制代码
-
通过postman模拟请求查看日志打印信息,在多次触发了fallback之后,随后将只返回了bike-business结果
c.b.h.controller.BikeHystrixController : this is hystrix err c.b.h.controller.BikeHystrixController : hystrix resp : 8126 c.b.h.controller.BikeHystrixController : hystrix resp : 8126 c.b.h.controller.BikeHystrixController : hystrix resp : 8126 c.b.h.controller.BikeHystrixController : hystrix resp : 8126 c.b.h.controller.BikeHystrixController : hystrix resp : 8126 c.b.h.controller.BikeHystrixController : hystrix resp : 8126 复制代码
-
-
三、openFeign的集成
-
pom依赖
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency> 复制代码
-
启动配置
@SpringBootApplication(exclude = DataSourceAutoConfiguration.class) @EnableDiscoveryClient @EnableCircuitBreaker @EnableHystrixDashboard @EnableFeignClients//开启feign public class BikeHystrixApplication { public static void main(String[] args) { SpringApplication.run(BikeHystrixApplication.class, args); } } 复制代码
-
配置文件
feign: hystrix: enabled: true #开启熔断支持 复制代码
-
测试验证
-
配置feignClient
//通过配置fallbackFactory指定服务降级的类 @FeignClient(value = "bike-business",fallbackFactory = FallbackFactory.class) public interface BikeHystrixFeignClient { @GetMapping("/bike-business/hystrix") String hystrix(); } 复制代码
-
服务降级实现
/** * 实现FallbackFactory接口 */ @Component @Slf4j public class FallbackFactory implements feign.hystrix.FallbackFactory<BikeHystrixFeignClient> { @Override public BikeHystrixFeignClient create(Throwable throwable) { log.error(throwable.getMessage()); //通过匿名内部类来自定义异常情况的返回数据 return new BikeHystrixFeignClient(){ @Override public String hystrix() { return throwable.getMessage(); } }; } } 复制代码
-
测试验证
在controller新增feign调用接口,在验证的过程中,如果bike-business服务有一个节点停掉,那么feign就会进行单节点熔断,当服务重启时,服务又会自动分发到重启的节点,当所有bike-business节点服务都不可用时,触发FallbackFactory的实现。
-
四、仪表盘
-
pom依赖
<!-- 新增仪表盘依赖 --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId> </dependency> 复制代码
-
启动配置
@SpringBootApplication @EnableDiscoveryClient @EnableCircuitBreaker//开启断路器 @EnableHystrixDashboard//开启仪表盘 public class BikeHystrixApplication { public static void main(String[] args) { SpringApplication.run(BikeHystrixApplication.class, args); } /** * 设置负载均衡 * @return */ @Bean @LoadBalanced RestTemplate restTemplate(){ return new RestTemplate(); } } 复制代码
-
配置文件
hystrix: command: default: execution: timeout: #是否开启超时熔断 enabled: true isolation: #hystrix隔离策略 #SEMAPHORE - 它在调用线程上执行,并发请求受信号量计数的限制(Zuul默认此策略) #THREAD - 它在一个单独的线程上执行,并发请求受到线程池中线程数的限制 strategy: SEMAPHORE #如果仪表盘的Thread Pools一直处于loading状态,那么可设置为Therad隔离策略 thread: timeoutInMilliseconds: 2000 # 设置hystrix的超时时间为2s #添加本地代理列表 dashboard: proxy-stream-allow-list: "localhost" #暴露全部的监控信息 management: endpoints: web: exposure: include: "*" 复制代码
-
测试验证
- Deplay 该参数用来控制服务器上轮询监控信息的延迟时间,默认是2000毫秒,可以通过配置该属性来降低客户端的网络和cpu消耗。
- Title该参数对应了头部标题Hystrix Stream之后的内容,默认会使用哦具体监控实例的URL,可疑通过配置该信息来展示更合适的标题。
-
根据Hystrix Dashboard提示填写具体监测的服务,比如单节点Single Hystrix App填写https://hystrix-app:port/actuator/hystrix.stream
-
查看监控参数
- 实心圆:共有两种含义。它通过颜色的变化代表了实例的健康程度,它的健康程度从 绿色 > 黄色 > 橙色 > 红色 递减;它的大小也会根据实例的请求流量发生变化,流量越大实心圆就越大,所以通过该实心圆的展示,就可以在大量实例中快速的发现故障实例和高压力实例
- 百分数:最近10s错误百分比
- circuit:断路状态
-
模拟熔断
-
停掉远程服务bike-business所有节点,再通过feign频繁请求远程服务,观察仪表盘的状态变化
-
postman返回请求信息为Hystrix circuit short-circuited and is OPEN。
-