首先,阅读HystrixPlugin源码
@Slf4j
public class HystrixPlugin extends AbstractSoulPlugin {
@Override
protected Mono<Void> doExecute(final ServerWebExchange exchange, final SoulPluginChain chain, final SelectorData selector, final RuleData rule) {
final SoulContext soulContext = exchange.getAttribute(Constants.CONTEXT);
assert soulContext != null;
final HystrixHandle hystrixHandle = GsonUtils.getInstance().fromJson(rule.getHandle(), HystrixHandle.class); // 获取Hystrix的规则配置相关信息
if (StringUtils.isBlank(hystrixHandle.getGroupKey())) { // 补充设置groupkey
hystrixHandle.setGroupKey(Objects.requireNonNull(soulContext).getModule());
}
if (StringUtils.isBlank(hystrixHandle.getCommandKey())) { // 补充设置commandkey
hystrixHandle.setCommandKey(Objects.requireNonNull(soulContext).getMethod());
}
Command command = fetchCommand(hystrixHandle, exchange, chain);
return Mono.create(s -> {
Subscription sub = command.fetchObservable().subscribe(s::success,
s::error, s::success); // 访问成功和访问失败的操作
s.onCancel(sub::unsubscribe); // 定义取消订阅的操作
if (command.isCircuitBreakerOpen()) { // 被 hystrix 熔断 打印一条日志
log.error("hystrix execute have circuitBreaker is Open! groupKey:{},commandKey:{}", hystrixHandle.getGroupKey(), hystrixHandle.getCommandKey());
}
}).doOnError(throwable -> { // hystrix执行失败,打印日志后继续执行
log.error("hystrix execute exception:", throwable);
exchange.getAttributes().put(Constants.CLIENT_RESPONSE_RESULT_TYPE, ResultEnum.ERROR.getName());
chain.execute(exchange);
}).then();
}
private Command fetchCommand(final HystrixHandle hystrixHandle, final ServerWebExchange exchange, final SoulPluginChain chain) {
if (hystrixHandle.getExecutionIsolationStrategy() == HystrixIsolationModeEnum.SEMAPHORE.getCode()) { // 信号量模式 使用的HystrixCommand
return new HystrixCommand(HystrixBuilder.build(hystrixHandle),
exchange, chain, hystrixHandle.getCallBackUri());
}
return new HystrixCommandOnThread(HystrixBuilder.buildForHystrixCommand(hystrixHandle),
exchange, chain, hystrixHandle.getCallBackUri()); // 线程池模式 使用的HystrixCommand
}
@Override
public String named() {
return PluginEnum.HYSTRIX.getName();
}
@Override
public int getOrder() {
return PluginEnum.HYSTRIX.getCode();
}
}
对于信号量模式和线程池模式使用的是不同的HystrixCommand
信号量模式的HystrixCommand如下:
@Slf4j
public class HystrixCommand extends HystrixObservableCommand<Void> implements Command {
private final ServerWebExchange exchange;
private final SoulPluginChain chain;
private final URI callBackUri;
/**
* Instantiates a new Http command.
*
* @param setter the setter
* @param exchange the exchange
* @param chain the chain
* @param callBackUri the call back uri
*/
public HystrixCommand(final Setter setter,
final ServerWebExchange exchange,
final SoulPluginChain chain,
final String callBackUri) {
super(setter);
this.exchange = exchange;
this.chain = chain;
this.callBackUri = UriUtils.createUri(callBackUri);
}
@Override
protected Observable<Void> construct() {
return RxReactiveStreams.toObservable(chain.execute(exchange));
}
@Override
protected Observable<Void> resumeWithFallback() {
return RxReactiveStreams.toObservable(doFallback()); // 定义失败回调
}
private Mono<Void> doFallback() {
if (isFailedExecution()) {
log.error("hystrix execute have error: ", getExecutionException());
}
final Throwable exception = getExecutionException();
return doFallback(exchange, exception);
}
@Override
public Observable<Void> fetchObservable() {
return this.toObservable(); // 返回调用实例的包装对象
}
@Override
public URI getCallBackUri() {
return callBackUri;
}
}
它继承了 HystrixObservableCommand<Void> 使用它的 toObservable() 方法包装调用对象
线程池的HystrixCommand如下
@Slf4j
public class HystrixCommandOnThread extends HystrixCommand<Mono<Void>> implements Command {
private final ServerWebExchange exchange;
private final SoulPluginChain chain;
private final URI callBackUri;
/**
* Instantiates a new Http command.
*
* @param setter the setter
* @param exchange the exchange
* @param chain the chain
* @param callBackUri the call back uri
*/
public HystrixCommandOnThread(final HystrixCommand.Setter setter,
final ServerWebExchange exchange,
final SoulPluginChain chain,
final String callBackUri) {
super(setter);
this.exchange = exchange;
this.chain = chain;
this.callBackUri = UriUtils.createUri(callBackUri);
}
@Override
protected Mono<Void> run() {
RxReactiveStreams.toObservable(chain.execute(exchange)).toBlocking().subscribe(); // 不熔断继续访问后面的插件
return Mono.empty();
}
@Override
protected Mono<Void> getFallback() {
if (isFailedExecution()) {
log.error("hystrix execute have error: ", getExecutionException());
}
final Throwable exception = getExecutionException();
return doFallback(exchange, exception);
}
@Override
public Observable<Void> fetchObservable() {
return RxReactiveStreams.toObservable(this.execute()); // execute 方法调用
}
@Override
public URI getCallBackUri() {
return callBackUri;
}
}
它继承了 HystrixCommand<Mono<Void>> ,封装了它的execute方法 进行调用。