java迭代器删除元素原理,二十二

本文详细解释了HystrixCommandAspect中的execute方法,如何根据ExecutionType选择同步、异步或OBSERVABLE模式执行,涉及异步回调、信号量管理、熔断器逻辑和降级处理。作者以Java的Observer模式和回调函数式编程为例,剖析了Hystrix框架的内部执行机制。
摘要由CSDN通过智能技术生成

}

跟下去.HystrixCommandAspect#methodsAnnotatedWithHystrixCommand

public static Object execute(HystrixInvokable invokable, ExecutionType executionType, MetaHolder metaHolder) throws RuntimeException {

Validate.notNull(invokable);

Validate.notNull(metaHolder);

//ExecutionType有三种类型,同步执行,异步执行,OBSERVABLE异步回调,默认走SYNCHRONOUS

switch (executionType) {

//同步

case SYNCHRONOUS: {

//把 HystrixInvokable 转成 HystrixExecutable 后执行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();

}

//OBSERVABLE 模式

case OBSERVABLE: {

HystrixObservable observable = castToObservable(invokable);

return ObservableExecutionMode.EAGER == metaHolder.getObservableExecutionMode() ? observable.observe() : observable.toObservable();

}

default:

throw new RuntimeException("unsupported execution type: " + executionType);

}

}

//转发了一下类型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”);

}

该方法会根据传入的ExecutionType判断执行的方式,ExecutionType中有三种类型

  • ASYNCHRONOUS:异步执行,

  • SYNCHRONOUS:同步执行,

  • OBSERVABLE:异步回调,你可去百度一下Java的Observer,它其实是观察者的实现

默认走同步执行SYNCHRONOUS,先把 HystrixInvokable 转成 HystrixExecutable 后,执行execute 继续跟下去,代码来到:com.netflix.hystrix.HystrixCommand#execute

public R execute() {

try {

return queue().get();

} catch (Exception e) {

throw Exceptions.sneakyThrow(decomposeException(e));

}

}

public Future queue() {

/*

  • The Future returned by Observable.toBlocking().toFuture() does not implement the

  • interruption of the execution thread when the “mayInterrupt” flag of Future.cancel(boolean) is set to true;

  • thus, to comply with the contract of Future, we must wrap around it.

*/

final Future delegate = toObservable().toBlocking().toFuture();

…省略…

return f;

}

execute方法中调用了queue方法,queue方法中用到了观察者模式,在toObservable方法中可以看到hystrix的降级触发流程,在toFuture方法中最终会通过GennericCommand调用CommandAction去执行我们的方法,这里我关注toObservable源码如下;

public Observable toObservable() {

final AbstractCommand _cmd = this;

…省略…

//【第二步】回调

final Func0<Observable> applyHystrixSemantics = new Func0<Observable>() {

@Override

public Observable call() {

if (commandState.get().equals(CommandState.UNSUBSCRIBED)) {

return Observable.never();

}

//【第三步】

return applyHystrixSemantics(_cmd);

}

};

return Observable.defer(new Func0<Observable>() {

@Override

public Observable call() {

…省略…

//这里走缓存

/* try from cache first */

if (requestCacheEnabled) {

HystrixCommandResponseFromCache fromCache = (HystrixCommandResponseFromCache) requestCache.get(cacheKey);

if (fromCache != null) {

isResponseFromCache = true;

return handleRequestCacheHitAndEmitValues(fromCache, _cmd);

}

}

//【第一步】

Observable hystrixObservable =

Observable.defer(applyHystrixSemantics)

.map(wrapWithAllOnNextHooks);

…省略…

Hystrix大量使用到了类似于JS的回调函数式编程,applyHystrixSemantics 就是一个回调,通过 Observable.defer(applyHystrixSemantics) 去执行。applyHystrixSemantics 中又调用了 applyHystrixSemantics(_cmd);跟进com.netflix.hystrix.AbstractCommand#applyHystrixSemantics方法

private Observable applyHystrixSemantics(final AbstractCommand _cmd) {

// mark that we’re starting execution on the ExecutionHook

// if this hook throws an exception, then a fast-fail occurs with no fallback. No state is left inconsistent

executionHook.onStart(_cmd);

//是否允许执行熔断器,方法中判断电路是否打开,方法中会

//判断circuitBreakerForceOpen强制打开熔断器 和 circuitBreakerForceClosed强制关闭熔断器

/* determine if we’re allowed to execute */

if (circuitBreaker.attemptExecution()) {

//信号量

final TryableSemaphore executionSemaphore = getExecutionSemaphore();

final AtomicBoolean semaphoreHasBeenReleased = new AtomicBoolean(false);

//信号量释放的回调

final Action0 singleSemaphoreRelease = new Action0() {

@Override

public void call() {

if (semaphoreHasBeenReleased.compareAndSet(false, true)) {

executionSemaphore.release();

}

}

};

final Action1 markExceptionThrown = new Action1() {

@Override

public void call(Throwable t) {

eventNotifier.markEvent(HystrixEventType.EXCEPTION_THROWN, commandKey);

}

};

//尝试获取信号量

if (executionSemaphore.tryAcquire()) {

try {

/* used to track userThreadExecutionTime */

//创建一个执行结果对象

executionResult = executionResult.setInvocationStartTime(System.currentTimeMillis());

//执行command和监听

return executeCommandAndObserve(_cmd)

//当出现错误

.doOnError(markExceptionThrown)

.doOnTerminate(singleSemaphoreRelease)

.doOnUnsubscribe(singleSemaphoreRelease);

} catch (RuntimeException e) {

return Observable.error(e);

}

} else {

return handleSemaphoreRejectionViaFallback();

}

} else {

return handleShortCircuitViaFallback();

}

}

这里确定电路未打开的情况下,获取信号量,然后调用com.netflix.hystrix.AbstractCommand#executeCommandAndObserve方法,继续跟下去:

private Observable executeCommandAndObserve(final AbstractCommand _cmd) {

final HystrixRequestContext currentRequestContext = HystrixRequestContext.getContextForCurrentThread();

… 省略部分代码…

//【重要】这个是处理降级的回调,处理降级的核心流程

final Func1<Throwable, Observable> handleFallback = new Func1<Throwable, Observable>() {

@Override

public Observable call(Throwable t) {

//【第二步】降级

//标记未成功

circuitBreaker.markNonSuccess();

//拿到异常对象

Exception e = getExceptionFromThrowable(t);

executionResult = executionResult.setExecutionException(e);

//判断错误类型拒绝执行,超时等,做不同的处理

if (e instanceof RejectedExecutionException) {

//线程池拒绝

return handleThreadPoolRejectionViaFallback(e);

} else if (t instanceof HystrixTimeoutException) {

//超时

return handleTimeoutViaFallback();

} else if (t instanceof HystrixBadRequestException) {

//请求错误

return handleBadRequestByEmittingError(e);

} else {

/*

  • Treat HystrixBadRequestException from ExecutionHook like a plain HystrixBadRequestException.

*/

if (e instanceof HystrixBadRequestException) {

eventNotifier.markEvent(HystrixEventType.BAD_REQUEST, commandKey);

return Observable.error(e);

}

//处理失败

return handleFailureViaFallback(e);

}

}

};

return execution.doOnNext(markEmits)

.doOnCompleted(markOnCompleted)

//【第一步】这里执行错误,触发降级回调

.onErrorResumeNext(handleFallback)

.doOnEach(setRequestContext);

该方法中 Observable 去执行,如果出现错误会触发handleFallback降级回调,handleFallback#call方法中拿到异常后,进行处理,我们继续跟踪一下:com.netflix.hystrix.AbstractCommand#handleFailureViaFallback方法

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注Java获取)

img

读者福利

秋招我借这份PDF的复习思路,收获美团,小米,京东等Java岗offer

更多笔记分享

秋招我借这份PDF的复习思路,收获美团,小米,京东等Java岗offer

《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!
!**

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注Java获取)

img

读者福利

[外链图片转存中…(img-5JobuaBz-1713498495984)]

更多笔记分享

[外链图片转存中…(img-nNZKw2q9-1713498495985)]

《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值