Hystrix服务调用的内部逻辑
Hystrix 在SpringCloud的使用
给HystrixCommand设值
@GetMapping("/{id}")
@HystrixCommand(fallbackMethod = "errorCallBack")
public Book getBook(@PathVariable("id")Integer id){
show();
Book book = bookService.getBook(id);
if(book == null ){
throw new RuntimeException("查无此产品");
}
return book;
}
启用断路器
@SpringBootApplication
@EnableEurekaClient
@EnableDiscoveryClient
@EnableCircuitBreaker //启用断路器
public class ProHystrixApp {
public static void main(String[] args) {
SpringApplication.run(ProHystrixApp.class,args);
}
}
Hystrix源码分析
我们先看看@HystrixCommand
在注解中我们可以设置HystrixCommand的回退方法等各种参数
然后我们再看看看HystrixCommand一些参数
之后我们再来看看@EnableCircuitBreaker,这里引入了一个@Import(EnableCircuitBreakerImportSelector.class) 类,翻译类的名字就是 , 开启熔断器的导入选择器
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Import(EnableCircuitBreakerImportSelector.class)
public @interface EnableCircuitBreaker {
}
EnableCircuitBreakerImportSelector的作用就是去导入熔断器的配置 ,即会自动加载 jar包 spring-cloud-netflix-core 中的META-INF/spring.factories 中的Hystrix相关的自动配置类
@Order(Ordered.LOWEST_PRECEDENCE - 100)
public class EnableCircuitBreakerImportSelector
extends SpringFactoryImportSelector<EnableCircuitBreaker> {
@Override
protected boolean isEnabled() { //最后会返回一个true,表示开启断路器
return getEnvironment().getProperty("spring.cloud.circuit.breaker.enabled",
Boolean.class, Boolean.TRUE);
}
}
现在让我们来看看他是怎么实现的吧
EnableCircuitBreakerImportSelector继承了SpringFactoryImportSelector类,且它父类的泛型是EnableCircuitBreaker
通过构造方法,获得了一个EnableCircuitBreaker的对象
@SuppressWarnings("unchecked")
protected SpringFactoryImportSelector() {//获得一个EnableCircuitBreaker对象
this.annotationClass = (Class<T>) GenericTypeResolver
.resolveTypeArgument(this.getClass(), SpringFactoryImportSelector.class);
}
然后通过selectImports方法 ,在META-INF/spring.factories 目录下找到 的EnableCircuitBreaker 为key 对应的类HystrixCircuitBreakerConfiguration,然后把他加入到spring容器中。
HystrixCircuitBreakerConfiguration 就是针对于 Hystrix熔断器的配置
@Configuration
public class HystrixCircuitBreakerConfiguration {
//这是夜歌处理HystrixCommand的切面
@Bean
public HystrixCommandAspect hystrixCommandAspect() {
return new HystrixCommandAspect();
}
@Bean
public HystrixShutdownHook hystrixShutdownHook() {
return new HystrixShutdownHook();
}
@Bean
public HasFeatures hystrixFeature() {
return HasFeatures
.namedFeatures(new NamedFeature("Hystrix", HystrixCommandAspect.class));
}
private class HystrixShutdownHook implements DisposableBean {
@Override
public void destroy() throws Exception {
// Just call Hystrix to reset thread pool etc.
Hystrix.reset();
}
}
}
我们发现这个类中有HystrixCommandAspect,这就是我们联想到了之前的@HystrixCommand注解了,点进去看看
发现这有一个切入@HystrixCommand的切入点表达式
@Pointcut("@annotation(com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand)")
还有对这个切入点表达式处理的环绕增强
@Around("hystrixCommandAnnotationPointcut() || hystrixCollapserAnnotationPointcut()")
接下来我们仔细看下这个增强函数,它大概做的是通过@HystrixCommand`设置的参数给构造出一个HystrixCommand来,然后执行CommandExecutor.execute(invokable, executionType, metaHolder)
@Around("hystrixCommandAnnotationPointcut() || hystrixCollapserAnnotationPointcut()")
public Object methodsAnnotatedWithHystrixCommand(final ProceedingJoinPoint joinPoint) throws Throwable {
Method method = getMethodFromTarget(joinPoint);//获取目标函数
//非空判断
Validate.notNull(method, "failed to get method from joinPoint: %s", joinPoint);
//不能同时使用@HystrixCommand 和 @HystrixCollapser(请求合并器) 两个注解
if (method.isAnnotationPresent(HystrixCommand.class) && method.isAnnotationPresent(HystrixCollapser.class)) {
throw new IllegalStateException("method cannot be annotated with HystrixCommand and HystrixCollapser " +
"annotations at the same time");
}
MetaHolderFactory metaHolderFactory = META_HOLDER_FACTORY_MAP.get(HystrixPointcutType.of(method));
//metaHolder 封装了目标方法的返回、参数、proxy、同时使用setFallbackMethod,和 setDefaultProperties保存了一些Command的配置
MetaHolder metaHolder = metaHolderFactory.create(joinPoint);
//最后得到了一个GenericCommand
HystrixInvokable invokable = HystrixCommandFactory.getInstance().create(metaHolder);
//获取执行类型
ExecutionType executionType = metaHolder.isCollapserAnnotationPresent() ?
metaHolder.getCollapserExecutionType() : metaHolder.getExecutionType();
Object result;
try {
if (!metaHolder.isObservable()) {
//执行这个
result = CommandExecutor.execute(invokable, executionType, metaHolder);
} else {
result = executeObservable(invokable, executionType, metaHolder);
}
} catch (HystrixBadRequestException e) {
throw e.getCause();
} catch (HystrixRuntimeException e) {
throw hystrixRuntimeExceptionToThrowable(metaHolder, e);
}
return result;
}
HystrixCommandAspect 其实就是对 贴了@HystrixCommand标签的方法使用 Aop机制实现处理 。代码中通过把目标方法封装成 HystrixInvokable对象,通过CommandExecutor工具来执行目标方法。
追踪metaHolderFactory.create(joinPoint);,发现metaHolderFactory是一个接口,选择它的实现类CommandMetaHolderFactory
public MetaHolder create(Object proxy, Method method, Object obj, Object[] args, final ProceedingJoinPoint joinPoint) {
HystrixCommand hystrixCommand = method.getAnnotation(HystrixCommand.class);
//获取执行的形式 默认是同步的
ExecutionType executionType = ExecutionType.getExecutionType(method.getReturnType());
//
MetaHolder.Builder builder = metaHolderBuilder(proxy, method, obj, args, joinPoint);
if (isCompileWeaving()) {
builder.ajcMethod(getAjcMethodFromTarget(joinPoint));
}
return builder.defaultCommandKey(method.getName())
.hystrixCommand(hystrixCommand)
.observableExecutionMode(hystrixCommand.observableExecutionMode())
.executionType(executionType)
.observable(ExecutionType.OBSERVABLE == executionType)
.build();
}
追踪:ExecutionType executionType = ExecutionType.getExecutionType(method.getReturnType());
public static ExecutionType getExecutionType(Class<?> type) {//函数的返回值一般只是普通的对象
if (Future.class.isAssignableFrom(type)) {
return ExecutionType.ASYNCHRONOUS;
} else if (Observable.class.isAssignableFrom(type)) {
return ExecutionType.OBSERVABLE;
} else {
return ExecutionType.SYNCHRONOUS;//默认同步
}
}
这里我们知道了,ExecutionType默认是SYNCHRONOUS
看到metaHolderBuilder(proxy, method, obj, args, joinPoint),在这里设置了回退方法,以及一些默认配置
MetaHolder.Builder metaHolderBuilder(Object proxy, Method method, Object obj, Object[] args, final ProceedingJoinPoint joinPoint) {
MetaHolder.Builder builder = MetaHolder.builder()
.args(args).method(method).obj(obj).proxyObj(proxy)
.joinPoint(joinPoint);
//设置回退方法
setFallbackMethod(builder, obj.getClass(), method);
builder = setDefaultProperties(builder, obj.getClass(), joinPoint);
return builder;
}
创建完MetaHolder之后,就会根据MetaHolder创建HystrixInvokable。
回到增强函数那我们追踪:
HystrixInvokable invokable = HystrixCommandFactory.getInstance().create(metaHolder);
发现HystrixInvokable是一个空接口,他的目的只是用来标记可被执行,那么他是如何创建的,我们先看create()方法
public HystrixInvokable create(MetaHolder metaHolder) {
HystrixInvokable executable;
if (metaHolder.isCollapserAnnotationPresent()) {
executable = new CommandCollapser(metaHolder);
} else if (metaHolder.isObservable()) {
executable = new GenericObservableCommand(HystrixCommandBuilderFactory.getInstance().create(metaHolder));
} else {
//最终会进入这,返回一个GenericCommand
executable = new GenericCommand(HystrixCommandBuilderFactory.getInstance().create(metaHolder));
}
return executable;
}
最终返回的是一个GenericCommand,实现了HystrixCommand
追踪GenericCommand
@ThreadSafe
public class GenericCommand extends AbstractHystrixCommand<Object> {
private static final Logger LOGGER = LoggerFactory.getLogger(GenericCommand.class);
public GenericCommand(HystrixCommandBuilder builder) {
super(builder);
}
@Override
protected Object run() throws Exception {
LOGGER.debug("execute command: {}", getCommandKey().name());
return process(new Action() {
@Override
Object execute() {
return getCommandAction().execute(getExecutionType());
}
});
}
@Override
protected Object getFallback() {
final CommandAction commandAction = getFallbackAction();
if (commandAction != null) {
try {
return process(new Action() {
@Override
Object execute() {
MetaHolder metaHolder = commandAction.getMetaHolder();
Object[] args = createArgsForFallback(metaHolder, getExecutionException());
return commandAction.executeWithArgs(metaHolder.getFallbackExecutionType(), args);
}
});
} catch (Throwable e) {
LOGGER.error(FallbackErrorMessageBuilder.create()
.append(commandAction, e).build());
throw new FallbackInvocationException(unwrapCause(e));
}
} else {
return super.getFallback();
}
}
}
它本身对目标方法的正常执行和对 fallback方法的 执行做了实现 。
GenericCommand.this.getCommandAction().execute(…)获取到目标方法并执行,底层会交给 MethodExecutionAction 使用反射去执行方法
之后回到 HystrixCommandAspect的methodsAnnotatedWithHystrixCommand方法中,这是一个命令模式执行我们的方法.
Object result;
try {
是否响应式,默认为非响应式
if (!metaHolder.isObservable()) {
// 使用执行器 载入 Command、运行类型等,然后执行Command
result = CommandExecutor.execute(invokable, executionType, metaHolder);
} else {
result = executeObservable(invokable, executionType, metaHolder);
}
} catch (HystrixBadRequestException e) {
throw e.getCause();
} catch (HystrixRuntimeException e) {
throw hystrixRuntimeExceptionToThrowable(metaHolder, e);
}
return result;
我们追踪下execute()方法
public static Object execute(HystrixInvokable invokable, ExecutionType executionType, MetaHolder metaHolder) throws RuntimeException {
//非空判断
Validate.notNull(invokable);
Validate.notNull(metaHolder);
//三种运行类型 同步、异步、观察
switch (executionType) {
case SYNCHRONOUS: {
//我们进入默认的castToExecutable.execute()
return castToExecutable(invokable, executionType).execute();
}
case ASYNCHRONOUS: {
HystrixExecutable executable = castToExecutable(invokable, executionType);
if (metaHolder.hasFallbackMethodCommand()
&& ExecutionType.ASYNCHRONOUS == metaHolder.getFallbackExecutionType()) {
return new FutureDecorator(executable.queue());
}
return executable.queue();
}
case OBSERVABLE: {
HystrixObservable observable = castToObservable(invokable);
return ObservableExecutionMode.EAGER == metaHolder.getObservableExecutionMode() ? observable.observe() : observable.toObservable();
}
default:
throw new RuntimeException("unsupported execution type: " + executionType);
}
}
进入同步模式的castToExecutable(invokable, executionType),发现是一个返回值是接口HystrixExecutable,它的目的就是把HystrixInvokable类型转换成HystrixExecutable类型。
private static HystrixExecutable castToExecutable(HystrixInvokable invokable, ExecutionType executionType) {
if (invokable instanceof HystrixExecutable) {
return (HystrixExecutable) invokable;
}
throw new RuntimeException("Command should implement " + HystrixExecutable.class.getCanonicalName() + " interface to execute in: " + executionType + " mode");
}
并调用execute方法执行 ,跟踪execute方法进入HystrixCommand.execute方法中
public R execute() {
try {
return queue().get();
} catch (Exception e) {
throw Exceptions.sneakyThrow(decomposeException(e));
}
}
,HystrixCommand.execute(),实际是调用Future.get()来立即获取异步方法HystrixCommand.queue()的结果
我们先进入Future中看看他的一些方法
public interface Future<V> {
//可以用来停止一个任务,如果任务可以停止,则可以返回true,如果任务已经完成或者已经停止,或者无法停止,则会返回false.
boolean cancel(boolean mayInterruptIfRunning);
//判断当前方法是否取消
boolean isCancelled();
//判断当前方法是否完成
boolean isDone();
//方法可以当任务结束后返回一个结果,如果调用时,工作还没有结束,则会阻塞线程,直到任务执行完毕
V get() throws InterruptedException, ExecutionException;
//做多等待timeout的时间就会返回结果
V get(long timeout, TimeUnit unit)
throws InterruptedException, ExecutionException, TimeoutException;
}
Future是一个接口,他提供给了我们方法来检测当前的任务是否已经结束,还可以等待任务结束并且拿到一个结果,通过调用Future的get()方法可以当任务结束后返回一个结果值,如果工作没有结束,则会阻塞当前线程,直到任务执行完毕,我们可以通过调用cancel()方法来停止一个任务,
这个future的实际处理委派给 f 实现,f是匿名内部类,当调用queue().get()方法时,最终调用 delegate.get() 方法 ,而delegate是toObservable()获取一个Observable对象,然后使其阻塞,之后转化得到的Future。
public Future<R> queue() {
// 创建一个委派对象
final Future<R> delegate = toObservable().toBlocking().toFuture();
//f封
final Future<R> f = new Future<R>() {
......
};
.....
return f;
}
值,如果工作没有结束,则会阻塞当前线程,直到任务执行完毕,我们可以通过调用cancel()方法来停止一个任务,
这个future的实际处理委派给 f 实现,f是匿名内部类,当调用queue().get()方法时,最终调用 delegate.get() 方法 ,而delegate是toObservable()获取一个Observable对象,然后使其阻塞,之后转化得到的Future。
public Future<R> queue() {
// 创建一个委派对象
final Future<R> delegate = toObservable().toBlocking().toFuture();
//f封
final Future<R> f = new Future<R>() {
......
};
.....
return f;
}