Hystrix 是springcloud生态的断路器(隔离、限流、降级),主要是用来预防服务雪崩现象,剔除掉分布式系统中某些挂掉或请求过慢的服务节点。Hystrix 是一个帮助解决分布式系统中超时处理和容错的类库, 拥有保护系统的能力。
Hystrix的设计原则,
- 防止任何单个依赖项耗尽所有容器(如Tomcat)用户线程。
- 甩掉包袱,快速失败而不是排队。
- 在任何可行的地方提供回退,以保护用户不受失败的影响。
- 使用隔离技术(如隔离板、泳道和断路器模式)来限制任何一个依赖项的影响。
- 通过近实时的度量、监视和警报来优化发现时间。
- 通过配置的低延迟传播来优化恢复时间。
- 支持对Hystrix的大多数方面的动态属性更改,允许使用低延迟反馈循环进行实时操作修改。
- 避免在整个依赖客户端执行中出现故障,而不仅仅是在网络流量中。
一、Hystrix 的隔离策略(隔离、限流、降级)
微服务使用Hystrix熔断器实现了服务的自动降级,让微服务具备自我保护的能力,提升了系统的稳定性,也较好的解决雪崩效应。Hystrix断路器有两种隔离策略:信号量隔离(默认)和线程池隔离。
1、信号量模式
信号量模式,从始至终都只有请求线程自身,是同步调用模式,不支持超时调用,不支持直接熔断,由于没有线程的切换,开销非常小。
信号量隔离,常用于获取共享资源的场景中,比如计算机连接了两个打印机,那么初始的信号量就是2,被某个进程或线程获取后减1,信号量为0后,一般情况下,需要获取的线程或进程进入资源等待状态。Hystrix的处理有些不同,其不等待,直接返回失败。
2、线程池模式
线程池模式,可以支持异步调用,支持超时调用,支持直接熔断,存在线程切换,开销大。
线程池隔离,采用的就是jdk的线程池,其默认选用不使用阻塞队列的线程池,例如线程池大小为10,如果某时刻10个线程均被使用,那么新的请求将不会进入等待队列,而是直接返回失败,起到限流的作用。
3、断路器机制
断路器机制,当断路器处于打开状态时,直接返回失败或进入降级流程。断路器打开和关闭的触发流程为,
- 当总的请求数达到阈值或总的请求失败百分比达到了阈值时,将断路器的状态由关闭设置为打开。
- 当断路器打开时,所有的请求均被短路,在经过指定休眠时间窗口后,让下一个请求通过(断路器被认为是半开状态)。如果请求失败,断路器进入打开状态,并进入新的休眠窗口;否则进入关闭状态。
二、Hystrix 的整体处理流程
流程如上图所示,Hystrix 框架通过命令模式来实现方法粒度上的服务保障。
- HystrixCommand 类,提供同步的
execute
和异步的queue
方法。 - HystrixObservableCommand 类提供立即执行
observe
和延迟执行toObservable
的回调方法。 - 此外,实际项目中通常不会使用Hystrix集成的本地缓存。
三、 Hystrix 如何解决服务间的依赖调用隔离
微服务分布式架构下,众多的服务节点,没有断路器的保护,挂掉或者响应慢的节点有引发服务雪崩的风险,我们来看下 Hystrix 是如何解决服务间的依赖调用的。
- Hystrix 使用命令模式 HystrixCommand 包装依赖调用逻辑,每个命令在单独线程中/信号授权下执行。
- 可配置依赖调用超时时间,超时时间一般设为比99.5%平均时间略高即可。当调用超时时,直接返回或执行fallback逻辑。
- 为每个依赖提供一个小的线程池(或信号),如果线程池已满调用将被立即拒绝,默认不采用排队,加速失败判定时间。
- 依赖调用结果分:成功,失败(抛出异常),超时,拒绝,短路。 请求失败(异常,拒绝,超时,短路)时执行 fallback(降级)逻辑。
- 提供熔断器组件,可以自动运行或手动调用,停止当前依赖一段时间(10秒),熔断器默认错误率阈值为50%,超过将自动运行。
- 提供近实时依赖的统计和监控。
四、Hystrix 的使用示例
1、在springcloud中的使用
Hystrix 在springcloud中的使用,我们主要关注两个注解 @EnableCircuitBreaker 和 @HystrixCommand 。
- @EnableCircuitBreaker,加在程序的启动类上,表明开启Hystrix断路器。
- @HystrixCommand,加在具体的方法上,实现断路器功能,可以加 fallbackMethod 等参数。
a、启动类上开启Hystrix断路器
@SpringBootApplication
@EnableEurekaClient
@EnableCircuitBreaker // 开启 Hystrix 断路器
public class RibbonConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(RibbonConsumerApplication.class, args);
}
@Bean
@LoadBalanced
public RestTemplate restTemplate(){
return new RestTemplate();
}
}
b、方法上加@HystrixCommand注解,实现断路器功能
@Service
public class ConsumerService {
@Autowired
private RestTemplate restTemplate;
@HystrixCommand(fallbackMethod = "helloFallback")
public String helloService() {
return restTemplate.getForEntity("http://service-1/sayHi", String.class).getBody();
}
public String helloFallback(){
return "exception....";
}
}
2、Hystrix 命令设计模式
此方式较繁琐,不常用,建议直接在springcloud模式下使用,只需两个注解。
Hystrix使用了命令设计模式,只需要编写命令,继承HystrixCommand类,如下,
public class CommandHelloWorld extends HystrixCommand<String> {
private final String name;
public CommandHelloWorld(String name) {
super(HystrixCommandGroupKey.Factory.asKey("HelloWorld"));
this.name = name;
}
@Override
protected String run() throws Exception { // 完成业务逻辑
return "Hello " + name + "!";
}
@Override
protected String getFallback() { // run方法抛出异常的时候返回备用结果
return "Hello Failure " + name + "!";
}
}
测试,
@Test
public void test() {
assertEquals("Hello World!", new CommandHelloWorld("World").execute());
assertEquals("Hello Format!", new CommandHelloWorld("Format").execute());
}
五、hystrix-dashboard 监控
Hystrix Dashboard 提供了对于微服务调用状态的监控信息,需要结合spring-boot-actuator模块一起使用。Hystrix Dashboard 主要用来实时监控Hystrix的各项指标信息。通过Hystrix Dashboard反馈的实时信息,可以帮助我们快速发现系统中存在的问题。
1、引入依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix-dashboard</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
2、启动类开启 @EnableHystrixDashboard 注解
@SpringBootApplication
@EnableHystrixDashboard
public class HystrixDashboardApplication {
public static void main(String[] args) {
SpringApplication.run(RibbonConsumerApplication.class, args);
}
}
3、访问监控页面