Hystrix是什么
Hystrix 是 Netflix(美国一家在线影片租赁商)发源的项目,旨在控制分布式系统中提供更大容限和服务失败之间的相互关系。Hystrix隔离访问的远程服务、网络应用或者第三方的库点,防止级联失败故障,从而使复杂的分布式系统更具有弹性。
Hystrix源于Netflix API团队在2011年启动的弹性工程工作,而目前它在Netflix每天处理着数百亿的隔离线程以及数千亿的隔离信号调用。
内部通过舱壁隔离使请求互不影响,熔断器机制使本次请求Fast Fail 。这两种机制对互联网分布式系统来说至关重要,一个分布式服务会依赖数百个服务,而每一个依赖都可能出现延迟。特别是在一个访问高峰点,瞬间所有的资源都会耗尽在这个延迟的依赖上,设置拖垮整个服务,而隔离可以保证只有这一个依赖不可用,其他服务可以正常运行。熔断器机制能让请求Fast Fail ,再次发起请求,而不是一直在等着响应,缩短客户端的等待时间。
为什么用Hystrix
在一个复杂的分布式架构系统中,依赖服务是避免不了的,特别是在一个微服务化的时代。如果一个系统不能对相关的依赖进行隔离,那该系统就会有被拖垮被宕机的风险。在一个高并发高访问量的系统中,当一个被依赖的服务出现网络连接缓慢、处理延迟等情况,在几分钟甚至几秒内,所有的线程都会block在被依赖的资源上,进而导致所有资源被耗尽,系统被拖垮。
所有依赖服务都正常时:
当其中一个依赖出现延迟时,服务器的大部分线程都会block在依赖I上,在一个高流量的系统中,几秒内所有的线程资源都被blocking在了依赖上,从而导致系统的其他服务也不可用,甚至整个系统被拖垮,不可用。
Hystrix对依赖进行隔离和控制,通常这些依赖都是网络调用。Hystrix通过线程池和信号进行隔离,给每一个依赖分配指定的资源,当该依赖的资源不足(线程池爆满、信号tryAcquire) 就会直接返回失败,不会占用其他依赖的资源。
同时,Hystrix还提供了CircuitBreaker机制,当失败率达到某一个阀值时,Hystrix会Fast Fail 并迅速恢复,或者优雅的降级。
环境搭建
使用Maven搭建的项目,在pom.xml文件中引入hystrix-core坐标:
<dependency>
<groupId>com.netflix.hystrix</groupId>
<artifactId>hystrix-core</artifactId>
<version>1.4.18</version>
<artifactId>hystrix-core</artifactId>
<version>1.4.18</version>
</dependency>
环境搭建好之后就可以开发了,接下来会写如何开发Hystrix应用。
Hystrix开发
首先还从HelloWorld 开始,首先定义一个Command类,继承HystrixCommand
类,在构造函数中设置相关参数。重写run() 和 getFallback() ,业务逻辑实现放在run方法里。所有非HystrixBadRequestException
异常都会调用
getFallback方法,降级方案一般在getFallback方法中实现。
class HelloWorldCommand extends HystrixCommand<String> {
protected HelloWorldCommand(String name) {
super(HystrixCommand.Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey(name)));
}
@Override
protected String run() throws Exception {
System.out.println("run success " + Thread.currentThread().getName());
return "run success " + Thread.currentThread().getName();
}
protected HelloWorldCommand(String name) {
super(HystrixCommand.Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey(name)));
}
@Override
protected String run() throws Exception {
System.out.println("run success " + Thread.currentThread().getName());
return "run success " + Thread.currentThread().getName();
}
}
很简单,在run方法里面返回了当前的线程名字。执行下 TestCase ,观察打印数据
@Test
public void helloWorldCommand() {
HelloWorldCommand helloWorldCommand = new HelloWorldCommand("klov");
String result = helloWorldCommand.execute();
System.out.println("【HelloWorldCommand】 result = "+result);
public void helloWorldCommand() {
HelloWorldCommand helloWorldCommand = new HelloWorldCommand("klov");
String result = helloWorldCommand.execute();
System.out.println("【HelloWorldCommand】 result = "+result);
}
打印数据如下:
run success hystrix-klov-1
【HelloWorldCommand】 result = run success hystrix-klov-1
由输出数据可知线程池的名字默认是 hystrix+commandGroupKey+inde。
到此,Hystrix的开发环境以及基本的开发已经完成,后面会继续介绍Hystrix两个隔离方式的开发及原理。