Hystrix是SpringCloud全家桶中的熔断和隔离器,可实现服务的降级策咯、隔离策略、批量请求等等功能。
一般使用方法:
1.pom.xml中添加:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix</artifactId>
</dependency>
2.Application添加注解@EnableCircuitBreaker
@SpringBootApplication
@EnableCircuitBreaker
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
3.controller增加注解@HystrixCommand
@RestController
public class MyController {
@HystrixCommand(fallbackMethod = "error")
@RequestMapping(value = "/hello", method = RequestMethod.GET)
public String start(){
throw new RuntimeException();
// return "start";
}
public String error(){
return "error";
}
}
@HystrixCommand注解
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface HystrixCommand {
// 命令组key,用于将报告、报警、仪表盘等命令分组
String groupKey() default "";
// Hystrix命令key,默认为被修饰方法名
String commandKey() default "";
// HystrixThreadPool线程池的key,该key便于标识监控、度量发布、缓存中的线程池
String threadPoolKey() default "";
// 自定义的fallback方法
String fallbackMethod() default "";
// commandProperties相关参数
HystrixProperty[] commandProperties() default {};
// threadPoolProperties相关参数
HystrixProperty[] threadPoolProperties() default {};
// 可忽略的异常
Class<? extends Throwable>[] ignoreExceptions() default {};
// 分为LAZY和EAGER两种模式
ObservableExecutionMode observableExecutionMode() default ObservableExecutionMode.EAGER;
// 添加Hystrix执行期间所包含的想要抛出的异常
HystrixException[] raiseHystrixExceptions() default {};
// 默认fallback方法
String defaultFallback() default "";
}
@HystrixCommand注解执行过程
该注解也是基于aop实现的,其修饰的方法会进入HystrixCommandAspect中的methodsAnnotatedWithHystrixCommand()方法,该Aspect中仅实现了切面的Around方式。源码如下:
@Pointcut("@annotation(com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand)")
public void hystrixCommandAnnotationPointcut() {
}
@Pointcut("@annotation(com.netflix.hystrix.contrib.javanica.annotation.HystrixCollapser)")
public void hystrixCollapserAnnotationPointcut() {
}
@Around("hystrixCommandAnnotationPointcut() || hystrixCollapserAnnotationPointcut()")
public Object methodsAnnotatedWithHystrixCommand(final ProceedingJoinPoint joinPoint) throws Throwable {
// 获取切点方法
Method method = getMethodFromTarget(joinPoint);
// 被修饰方法不能为null
Validate.notNull(method, "failed to get method from joinPoint: %s", joinPoint);
// @HystrixCommand和@HystrixCollapser不能同时使用
if (method.isAnnotationPresent(.class) && method.isAnnotationPresent(HystrixCollapser.class)) {
throw new IllegalStateException("method cannot be annotated with HystrixCommand and HystrixCollapser " +
"annotations at the same time");
}
// 构造metaHolderFactory根据类型(COMMAND和COLLAPSER)
MetaHolderFactory metaHolderFactory = META_HOLDER_FACTORY_MAP.get(HystrixPointcutType.of(method));
// 创建metaHolder,其中包含了各种必要信息,如注解的方法包含的各种信息以及fallback方法的各种信息,下面有源码
MetaHolder metaHolder = metaHolderFactory.create(joinPoint);
// 创建一个可执行器,下面有源码
HystrixInvokable invokable = HystrixCommandFactory.getInstance().create(metaHolder);
// 设置类型SYNCHRONOUS、ASYNCHRONOUS、OBSERVABLE
ExecutionType executionType = metaHolder.isCollapserAnnotationPresent() ?
metaHolder.getCollapserExecutionType() : metaHolder.getExecutionType();
Object result;
try {
if (!metaHolder.isObservable()) {
// 默认会执行这里,根据不同情况返回结果,也是通过Futrue方式执行请求,通过get()方法获取结果,下面有源码
result = CommandExecutor.execute(invokable, executionType, metaHolder);
} else {
result = executeObservable(invokable, executionType, metaHolder);
}
} catch (HystrixBadRequestException e) {
throw e.getCause() != null ? e.getCause() : e;
} catch (HystrixRuntimeException e) {
throw hystrixRuntimeExceptionToThrowable(metaHolder, e);
}
return result;
}
metaHolderFactory.create(joinPoint)调用的create是MetaHolderFactory的重构方法,实际上是调用下面的create方法。
public abstract MetaHolder create(Object proxy, Method method, Object obj, Object[] args, final ProceedingJoinPoint 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);
// 此处就是添加fallback方法
setFallbackMethod(builder, obj.getClass(), method);
builder = setDefaultProperties(builder, obj.getClass(), joinPoint);
return builder;
}
HystrixCommandFactory.getInstance().create(metaHolder)调用的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 {
// 默认情况都会执行这里
executable = new GenericCommand(HystrixCommandBuilderFactory.getInstance().create(metaHolder));
}
return executable;
}
最终的方法执行
public static Object execute(HystrixInvokable invokable, ExecutionType executionType, MetaHolder metaHolder) throws RuntimeException {
Validate.notNull(invokable);
Validate.notNull(metaHolder);
switch (executionType) {
case SYNCHRONOUS: {
// 最终会执行这里的execute()方法,实际上调用的是queue().get()
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);
}
}
getFallback方法
上面一直没提到getFallback()方法,这个方法是在全流程中出现异常时,自动跳入的,源码中也有相关说明
/**
* The fallback is performed whenever a command execution fails.
*/
@Override
protected Object getFallback() {
// 获取fallback方法的执行器
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();
}
}
HystrixCommandExecutionHook
可能看了源码很多人也都有疑问,为什么出现异常就会转入getFallback方法,这是由于Hystrix使用了hook钩子,中包含了很多未实现的抽象方法。仔细看源码会发现在最开始初始化各个Hystrix参数的时候就初始化了hook。
protected AbstractCommand(HystrixCommandGroupKey group, HystrixCommandKey key, HystrixThreadPoolKey threadPoolKey, HystrixCircuitBreaker circuitBreaker, HystrixThreadPool threadPool,
HystrixCommandProperties.Setter commandPropertiesDefaults, HystrixThreadPoolProperties.Setter threadPoolPropertiesDefaults,
HystrixCommandMetrics metrics, TryableSemaphore fallbackSemaphore, TryableSemaphore executionSemaphore,
HystrixPropertiesStrategy propertiesStrategy, HystrixCommandExecutionHook executionHook) {
this.commandGroup = initGroupKey(group);
this.commandKey = initCommandKey(key, getClass());
this.properties = initCommandProperties(this.commandKey, propertiesStrategy, commandPropertiesDefaults);
this.threadPoolKey = initThreadPoolKey(threadPoolKey, this.commandGroup, this.properties.executionIsolationThreadPoolKeyOverride().get());
this.metrics = initMetrics(metrics, this.commandGroup, this.threadPoolKey, this.commandKey, this.properties);
this.circuitBreaker = initCircuitBreaker(this.properties.circuitBreakerEnabled().get(), circuitBreaker, this.commandGroup, this.commandKey, this.properties, this.metrics);
this.threadPool = initThreadPool(threadPool, this.threadPoolKey, threadPoolPropertiesDefaults);
//Strategies from plugins
this.eventNotifier = HystrixPlugins.getInstance().getEventNotifier();
this.concurrencyStrategy = HystrixPlugins.getInstance().getConcurrencyStrategy();
HystrixMetricsPublisherFactory.createOrRetrievePublisherForCommand(this.commandKey, this.commandGroup, this.metrics, this.circuitBreaker, this.properties);
this.executionHook = initExecutionHook(executionHook);
this.requestCache = HystrixRequestCache.getInstance(this.commandKey, this.concurrencyStrategy);
this.currentRequestLog = initRequestLog(this.properties.requestLogEnabled().get(), this.concurrencyStrategy);
/* fallback semaphore override if applicable */
this.fallbackSemaphoreOverride = fallbackSemaphore;
/* execution semaphore override if applicable */
this.executionSemaphoreOverride = executionSemaphore;
}
最终的实现都是在ExecutionHookDeprecationWrapper类中实现的具体逻辑,该类是HystrixCommandExecutionHook抽象类的子类。
这就是Hystrix中getFallback方法的实现原理。

454

被折叠的 条评论
为什么被折叠?



