hystrix插件
根据官网的介绍,hystrix插件是网关用来对流量进行熔断的核心实现。查看代码可以发现,
- HystrixPlugin extends AbstractSoulPlugin
- AbstractSoulPlugin implements SoulPlugin
SoulPlugin 是一个接口,接口定义了4个方法execute,getOrder,named,skip。execute是执行方法,getorder是获取优先级,named获取的是插件名,skip方式是判断是否跳过该插件。
AbstractSoulPlugin是插件的抽象类,以下17个是继承的类。HystrixPlugin是其中一个。
以下是AbstractSoulPlugin.execute方法。
public Mono<Void> execute(final ServerWebExchange exchange, final SoulPluginChain chain) {
// 获取插件名称
String pluginName = named();
// 根据插件名获取该插件的基本数据,如 PluginData(id=9, name=hystrix, config=null, role=0, enabled=true)
final PluginData pluginData = BaseDataCache.getInstance().obtainPluginData(pluginName);
// 要在 soul-admin 中将插件打开,否则web请求不会被此插件处理
if (pluginData != null && pluginData.getEnabled()) {
// 选择器数据
final Collection<SelectorData> selectors = BaseDataCache.getInstance().obtainSelectorData(pluginName);
if (CollectionUtils.isEmpty(selectors)) {
return handleSelectorIsNull(pluginName, exchange, chain);
}
final SelectorData selectorData = matchSelector(exchange, selectors);
if (Objects.isNull(selectorData)) {
return handleSelectorIsNull(pluginName, exchange, chain);
}
selectorLog(selectorData, pluginName);
// 规则列表
final List<RuleData> rules = BaseDataCache.getInstance().obtainRuleData(selectorData.getId());
if (CollectionUtils.isEmpty(rules)) {
return handleRuleIsNull(pluginName, exchange, chain);
}
RuleData rule;
if (selectorData.getType() == SelectorTypeEnum.FULL_FLOW.getCode()) {
//get last
rule = rules.get(rules.size() - 1);
} else {
rule = matchRule(exchange, rules);
}
if (Objects.isNull(rule)) {
return handleRuleIsNull(pluginName, exchange, chain);
}
ruleLog(rule, pluginName);
// 熔断逻辑
return doExecute(exchange, chain, selectorData, rule);
}
return chain.execute(exchange);
}
doExecute()方法中的断路器是判断熔断的关键:
@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;
// 从当前web请求匹配上的规则取出熔断配置
final HystrixHandle hystrixHandle = GsonUtils.getInstance().fromJson(rule.getHandle(), HystrixHandle.class);
if (StringUtils.isBlank(hystrixHandle.getGroupKey())) {
hystrixHandle.setGroupKey(Objects.requireNonNull(soulContext).getModule());
}
if (StringUtils.isBlank(hystrixHandle.getCommandKey())) {
// 没有配置 ‘命令Key’ 时,设置一个默认的
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()) {
log.error("hystrix execute have circuitBreaker is Open! groupKey:{},commandKey:{}", hystrixHandle.getGroupKey(), hystrixHandle.getCommandKey());
}
}).doOnError(throwable -> {
log.error("hystrix execute exception:", throwable);
exchange.getAttributes().put(Constants.CLIENT_RESPONSE_RESULT_TYPE, ResultEnum.ERROR.getName());
chain.execute(exchange);
}).then();
}
在PluginEnum中定义了code(优先级),role,和name。这里设置了HYSTRIX,SENTINEL,RESILIENCE4J的优先级都为45,数字越小优先级越高。
/**
* Hystrix plugin enum.
*/
HYSTRIX(45, 0, "hystrix"),
/**
* Sentinel plugin enum.
*/
SENTINEL(45, 0, "sentinel"),
/**
* Resilence4J plugin enum.
*/
RESILIENCE4J(45, 0, "resilience4j"),
Hystrix处理详解:
根据官网的解释,可以看到有如下配置。
-
跳闸最小请求数量 :最小的请求量,至少要达到这个量才会触发熔断
-
错误百分比阀值 : 这段时间内,发生异常的百分比。
-
最大并发量 : 最大的并发量
-
跳闸休眠时间(ms) :熔断以后恢复的时间。
-
分组Key: 一般设置为:contextPath
-
命令Key: 一般设置为具体的 路径接口。
具体界面如下图所示
这里附上官方文档flow chart