Soul网关中的Sentinel插件

本篇文章分析的是Sentinel插件,它也可以提供熔断和限流的功能。

操作前准备:启动soul-adminsoul网关,soul-examples-http测试用例。

Sentinel功能演示

首先在soul网关中添加Sentinel插件,引入依赖:

        <!-- soul sentinel plugin start-->
        <dependency>
            <groupId>org.dromara</groupId>
            <artifactId>soul-spring-boot-starter-plugin-sentinel</artifactId>
            <version>${project.version}</version>
        </dependency>
        <!-- soul sentinel plugin end-->

然后需要在soul-admin中依次开启插件,添加选择器,添加规则:

规则字段解析:

  • degrade count: 熔断阈值;
  • whether to open the degrade (1 or 0): 是否开启熔断;
  • degrade type: 熔断策略,支持秒级 RT/秒级异常比例/分钟级异常数;
  • control behavior: 流控策略(直接拒绝 / 排队等待 / 慢启动模式),不支持按调用关系限流;
  • grade count:限流阈值;
  • whether control behavior is enabled (1 or 0): 是否开启限流;
  • grade type: 限流类型,QPS 或线程数模式。

上述准备工作完成后,就能进行测试了。开启限流,设置流控阈值为1,然后多点几次 postman,即会发生限流现象:

Sentinel原理分析

SentinelPlugin 继承于模板抽象类 AbstractSoulPlugin,所以 doExecutor 是其执行真正功能逻辑的代码:

    protected Mono<Void> doExecute(final ServerWebExchange exchange, final SoulPluginChain chain, final SelectorData selector, final RuleData rule) {
		//省略了其他代码
        SentinelHandle sentinelHandle = GsonUtils.getInstance().fromJson(rule.getHandle(), SentinelHandle.class);
        //限流或降级执行类 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));
    }

限流或降级执行类是 SentinelReactorTransformer,来自于Sentinel插件。集成Sentinel插件就是以上代码,使用起来还是比较简单。

Sentinel规则在admin修改后,会同步更新到SentinelRuleHandle

public void handlerRule(final RuleData ruleData) {
        SentinelHandle sentinelHandle = GsonUtils.getInstance().fromJson(ruleData.getHandle(), SentinelHandle.class);

        //更新限流规则
        List<FlowRule> flowRules = FlowRuleManager.getRules()
        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);
    }

小结,本文结合实际案例演示了Sentinel插件,跟踪了Sentinel插件源码。