Sentinel插件功能
Sentinel是面向分布式服务架构的高可用流量控制组件,为Soul网关提供流量控制和熔断降级功能。Sentinel插件使Soul网关与Sentinel组件进行整合。通过上篇介绍,使用者只需要少量配置即可使用。并且支持动态修改Sentinel的配置信息,不需要重启Soul网关应用。
Sentinel插件源码阅读
当客户端调用网关请求时,SentinelPlugin
类会执行,它的功能是判断该请求是否启动规则配置,如符合则调用Sentinel的流控或熔断功能。
SentinelPlugin.java
public class SentinelPlugin extends AbstractSoulPlugin {
@Override
protected Mono<Void> doExecute(final ServerWebExchange exchange, final SoulPluginChain chain, final SelectorData selector, final RuleData rule) {
// 通过HTTP Request,获取到SoulContext信息
final SoulContext soulContext = exchange.getAttribute(Constants.CONTEXT);
assert soulContext != null;
// 根据规则配置信息,生成资源名(选择ID + 规则名称)。 资源名是Sentinel的核心概念
String resourceName = SentinelRuleHandle.getResourceName(rule);
// 解析Sentinel的相关配置信息,如流控类型、流控策略、流控限值等等
SentinelHandle sentinelHandle = GsonUtils.getInstance().fromJson(rule.getHandle(), SentinelHandle.class);
// 处理一下plugin,SentinelReactorTransformer执行流控或熔断监控
return chain.execute(exchange).transform(new SentinelReactorTransformer<>(resourceName)).doOnSuccess(v -> {
if (exchange.getResponse().getStatusCode() != HttpStatus.OK) {
HttpStatus status = exchange.getResponse().getStatusCode();
exchange.getResponse().setStatusCode(null);
throw new SentinelFallbackException(status);
}
}).onErrorResume(throwable -> sentinelFallbackHandler.fallback(exchange, UriUtils.createUri(sentinelHandle.getFallbackUri()), throwable));
}
}
当Soul控制台更新流控或熔断的配置信息时,会将该信息同步给Soul网关,此时会调用SentinelRuleHandle
类,如下代码:
SentinelRuleHandle.java
public class SentinelRuleHandle implements PluginDataHandler {
// 当Soul控制台更新Sentinel相关配置信息时会调用此方法
@Override
public void handlerRule(final RuleData ruleData) {
SentinelHandle sentinelHandle = GsonUtils.getInstance().fromJson(ruleData.getHandle(), SentinelHandle.class);
// 获取Sentinel所有流控资源配置信息
List<FlowRule> flowRules = FlowRuleManager.getRules()
.stream()
// 如果要更新配置在List中,则过滤掉,以便添加最新的配置信息
.filter(r -> !r.getResource().equals(getResourceName(ruleData)))
.collect(Collectors.toList());
// 如果开启流控
if (sentinelHandle.getFlowRuleEnable() == Constants.SENTINEL_ENABLE_FLOW_RULE) {
// 创建Sentinel的流控规则
FlowRule rule = new FlowRule(getResourceName(ruleData));
// 流控限流阀值
rule.setCount(sentinelHandle.getFlowRuleCount());
// 流控类型,QPS或线程数
rule.setGrade(sentinelHandle.getFlowRuleGrade());
// 流控策略,直接拒绝、冷启动或匀速器
rule.setControlBehavior(sentinelHandle.getFlowRuleControlBehavior());
flowRules.add(rule);
}
// 创建资源规则
FlowRuleManager.loadRules(flowRules);
// 获取Sentinel所有熔断资源配置信息,
List<DegradeRule> degradeRules = DegradeRuleManager.getRules()
.stream()
// 如果要更新配置在List中,则过滤掉,以便添加最新的配置信息
.filter(r -> !r.getResource().equals(getResourceName(ruleData)))
.collect(Collectors.toList());
// 是否开启熔断
if (sentinelHandle.getDegradeRuleEnable() == Constants.SENTINEL_ENABLE_DEGRADE_RULE) {
// 创建熔断规则
DegradeRule rule = new DegradeRule(getResourceName(ruleData));
// 熔断阀值
rule.setCount(sentinelHandle.getDegradeRuleCount());
// 熔断策略 慢调用比例、异常比例或异常数
rule.setGrade(sentinelHandle.getDegradeRuleGrade());
// 熔断时长
rule.setTimeWindow(sentinelHandle.getDegradeRuleTimeWindow());
degradeRules.add(rule);
}
// 创建资源规则
DegradeRuleManager.loadRules(degradeRules);
}
// 删除流控和熔断
@Override
public void removeRule(final RuleData ruleData) {
FlowRuleManager.loadRules(FlowRuleManager.getRules()
.stream()
.filter(r -> !r.getResource().equals(getResourceName(ruleData)))
.collect(Collectors.toList()));
DegradeRuleManager.loadRules(DegradeRuleManager.getRules()
.stream()
.filter(r -> !r.getResource().equals(getResourceName(ruleData)))
.collect(Collectors.toList()));
}
}
总结
流量控制和熔断功能为系统提供了更高的稳定性。尤其是在微服务的体系下,避免了系统之间产生雪崩效应。做为网关,流量控制和熔断机制是必不可少的功能之一。