这世间许多事物皆因相信而存在,所以人们亲手捏出了泥菩萨,却选择坚定的去信仰它。
分布式系统的规模和复杂度不断增加,随着而来的是对分布式系统可用性的要求越来越高。在各种高可用设计模式中,【熔断、隔离、降级、限流】是经常被使用的。而相关的技术,Hystrix本身早已算不上什么新技术,但它却是最经典的技术体系!。
Hystrix以实现熔断降级的设计,从而提高了系统的可用性。
Hystrix是一个在调用端上,实现断路器模式,以及隔舱模式,通过避免级联故障,提高系统容错能力,从而实现高可用设计的一个Java服务组件库。
*Hystrix实现了资源隔离机制
介绍Hystrix的基本使用方式和基本配置
*使用Hystrix实现基本的熔断设计,以保护应用的安全,实现初步的高可用设计。
Hystrix的主要目的是保护跨进程调用,避免因为超时等问题,导致的级联故障。
*Hystrix的实现方法是封装跨进程调用。具体的使用方式有多种:从编程方式看可分为编程方式和注解方式两种;从调用方式看可分为同步调用方式、异步调用方式和反应式调用方式三种。
我们先来看最常见的同步编程方式:
public class AuthService {
private UserService userService;
public boolean validateUser(String userId) {
User user = new GetUserCommand(userId).execute();
if (user == null) {
return false;
} else {
return user.isValid();
}
}
class GetUserCommand extends HystrixCommand {
private Long userId;
public GetUserCommand(Long userId) {
super(Setter.withGroupKey(HystrixCommandGroupKey.
Factory.asKey("UserService"))
.andThreadPoolPropertiesDefaults(HystrixThreadPoolProperties.Setter()
.withCoreSize(20)
)
.andCommandPropertiesDefaults(HystrixCommandProperties.Setter()
.withExecutionTimeoutInMilliseconds(100)
)
);
this.userId = userId;
}
public User run() throws Exception {
return userService.getUserById(userId);
}
public User getFallback() {
return new InvalidUser();
}
}
}
复制代码
Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey("UserService"))
复制代码
.andThreadPoolPropertiesDefaults(HystrixThreadPoolProperties.Setter().withCoreSize(20))
复制代码
.andCommandPropertiesDefaults(HystrixCommandProperties.Setter().withExecutionTimeoutInMilliseconds(100)
复制代码
上面的部分介绍了HystrixCommand的基本使用方法,但只是简单介绍了几个配置。所以,下面将对 HystrixCommand的相关配置的作用做一个较为详细的介绍。
Hystrix的配置有三个维度: 全局默认配置、Instance默认配置、Instance动态配置。除了少部分配置项外,大部分配置都支持动态修改。
接下来介绍一下一些主要参数的Instance默认配置方式。这种配置方式也是使用Hystrix最先接触到的配置方式。
GroupKey是HystrixCommand不可缺少的配置,其它配置均为可选。所以,使用Hystrix可以使用下面的代码:
public class CommandHelloWorld extends HystrixCommand {
private final String name;
public CommandHelloWorld(String name) {
super(HystrixCommandGroupKey.Factory.asKey("ExampleGroup"));
this.name = name;
}
protected String run() {
return "Hello " + name + "!";
}
}
复制代码
HystrixCommandGroupKey是一个接口,除了可以HystrixCommandGroupKey.Factory.asKey(“ExampleGroup”) 的方式定义以外,也可以直接实现这个接口。比如使用如下的方式:
public enum Groups implements HystrixCommandGroupKey {
GROUP_1
}
class EnumGroupCommand extends HystrixCommand {
EnumGroupCommand() {
super(Groups.GROUP_1);
}
protected String run() throws Exception {
LOGGER.info("Thread of Command: {}", Thread.currentThread().getName());
return null;
}
}
复制代码
如上面代码这样,使用自定义的枚举类,实现HystrixCommandGroupKey接口,可以统一Hystrix Command Group的定义,简化配置。
HystrixCommandGroupKey的作用主要有两个:
虽然HystrixCommandGroupKey可以起到隔离线程池的作用,但是无法起到对线程池进行精细配置的作用。
所以这里就需要线程池进行配置:
Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey("MyService"))
.andThreadPoolKey(HystrixThreadPoolKey.Factory.asKey("MyThreadPool"))
.andThreadPoolPropertiesDefaults(HystrixThreadPoolProperties.Setter()
.withCoreSize(10)
.withKeepAliveTimeMinutes(1)
.withMaxQueueSize(-1)
)
)
复制代码
andThreadPoolPropertiesDefaults配置中的数值表示的是默认值。
接下来逐项介绍:
命令执行直接相关的配置,包括隔离策略、超时时间、Fallback相关配置。
接下来介绍几个主要的配置:
默认的隔离策略是实现线程池隔离,另外一种隔离策略是Semaphore。Instance默认配置可使用如下方法设置:
HystrixCommandProperties.Setter().withExecutionIsolationStrategy(ExecutionIsolationStrategy.SEMAPHORE)
复制代码
这项配置通常不用配置
默认时间是1000ms,单位是毫秒。
Instance默认配置可以使用如下方法设置:
.andCommandPropertiesDefaults(HystrixCommandProperties.Setter().withExecutionTimeoutInMilliseconds(100))
复制代码
这项配置比较重要,后文还会详细介绍如何调配这个参数。
在Instance默认配置中是通过如下代码设置的:
super(Setter.withGroupKey(BASIC_USAGE_GROUP)
.andCommandPropertiesDefaults(HystrixCommandProperties.Setter()
.withFallbackIsolationSemaphoreMaxConcurrentRequests(10)
)
);
复制代码