【高性能网关soul学习】18. 熔断限流插件之 Sentinel
本文目标:
- 分析 soul 插件 SentinelPlugin 集成 Sentinel 的代码
- 不涉及 sentinel 实现限流熔断的代码
Sentinel
Sentinel是阿里开源的一个项目,以流量为切入点,从流量控制、熔断降级、系统负载保护等多个维度保护服务的稳定性。
- 实时的监控功能、开箱即用的与其他开源那框架/库的整合模块、本身简单易用、完善的 SPI 扩展点
Soul 中 Sentinel 插件启动流程
-
soul-bootstrap 增加
soul-spring-boot-starter-plugin-sentinel
依赖- 依次启动 soul-admin、http测试服务、soul-bootstrap 网关服务
-
打开 系统管理 >> 插件 >> 启用 Sentinel 插件
-
打开 插件列表 >> Sentinel >> 选择器和规则配置
-
参考 选择器配置规则
-
注意限流和熔断的开启
-
是否开启流控(1或0) :是否开启sentinel的流控。
流控效果 : 流控效果(直接拒绝 / 排队等待 / 慢启动模式),不支持按调用关系限流。
限流阈值类型 : 限流阈值类型,QPS 或线程数模式。
是否开启熔断(1或0) :是否开启sentinel熔断。
熔断类型: 熔断策略,支持秒级 RT/秒级异常比例/分钟级异常数。
熔断阈值: 阈值。
熔断窗口大小: 降级的时间,单位为 s。
熔断URI: 熔断后的降级uri。
SentinelPlugin 和 流控熔断规则变更加载
SentinelPlugin 继承于 AbstractSoulPlugin, 因此和其他流量插件一样,核心方法为 doExecute
- 其中 sentinelHandle 包含在admin中配置的 sentinel 的各个开关参数
@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;
String resourceName = SentinelRuleHandle.getResourceName(rule);
// 配置的 sentinel 控制参数上下文
SentinelHandle sentinelHandle = GsonUtils.getInstance().fromJson(rule.getHandle(), SentinelHandle.class);
// SentinelReactorTransformer执行流控或熔断监控
return chain.execute(exchange).transform(new SentinelReactorTransformer<>(resourceName)).doOnSuccess(v -> {
// 插件链后续操作,调用后判断调用结果是否成功,不成功则抛出一个 sentinel 降级用的异常
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));
}
- admin 更新sentinel 的流控熔断 rule 数据时,最终会是SentinelRuleHandle 负责处理,并分别加载进 FlowRuleManager 和 DegradeRuleManager 中,
// SentinelRuleHandle.java 大致流程
@Override
public void handlerRule(final RuleData ruleData) {
SentinelHandle sentinelHandle = GsonUtils.getInstance().fromJson(ruleData.getHandle(), SentinelHandle.class);
List<FlowRule> flowRules = FlowRuleManager.getRules()
.stream()
.filter(r -> !r.getResource().equals(getResourceName(ruleData)))
.collect(Collectors.toList());
if (sentinelHandle.getFlowRuleEnable() == Constants.SENTINEL_ENABLE_FLOW_RULE) {
// 创建新的流控规则
}
FlowRuleManager.loadRules(flowRules);
// 获取已经存在的熔断规则
List<DegradeRule> degradeRules = DegradeRuleManager.getRules() ...
if (sentinelHandle.getDegradeRuleEnable() == Constants.SENTINEL_ENABLE_DEGRADE_RULE) {
// 创建新的降级熔断规则
}
DegradeRuleManager.loadRules(degradeRules);
}
总结
- 上述就是 soul 中对 sentinel 集成所做的工作,实际上最多的工作还是处理 admin 端配置rule数据时,将配置的规则load到 Sentinel 中的
FlowRuleManager
和DegradeRuleManager
- sentinel API简单易用,因此 sentinel 如何实现限流熔断都被封装了,调用者不需要关心
- sentinel 实现限流熔断的代码后续整理