Soul 源码解析(五)- 选择器和规则匹配

选择器和规则

Soul网关里的插件使用的是责任链的模式进行处理,所有流进网关的流量都会经过每个插件的处理;但是再插件处理之前,流量还需要经过Selector和rule的处理,过滤调不符合规则的流量数据。
话不多说,直接看代码;

选择器和规则器的代码位置

如图所示,选择器和规则的代码再soul-plugin - soul-plugin-base - AbstractSoulPlugin下;
在这里插入图片描述

代码解析

  • 一个插件对应多个选择器,一个选择器对应多个规则;在进行选择器和规则选择的时候,首先判断选择器存不存在,如果不存在,直接判断插件是否为waf\divide\dubbo\springcloud,如果不是其中插件则直接打印一条错误日志,插件执行失败,匹配不到;
  • 如果存在则会继续向下去匹配规则;规则的匹配和选择器的匹配一样,通过选择器去查询对应的规则,同时和uri进行匹配,获取对应的规则;如果规则为空则断插件是否为waf\divide\dubbo\springcloud,如果不是其中插件则直接打印一条错误日志,插件执行失败,匹配不到;
  • 流程如图所示:
    在这里插入图片描述
@Override
    public Mono<Void> execute(final ServerWebExchange exchange, final SoulPluginChain chain) {
        // 获取plugin name
        String pluginName = named();
        // 获取插件的信息
        final PluginData pluginData = BaseDataCache.getInstance().obtainPluginData(pluginName);
        if (pluginData != null && pluginData.getEnabled()) {
            // obtainSelectorData会通过plugin 名称去获取该插件的选择器
            final Collection<SelectorData> selectors = BaseDataCache.getInstance().obtainSelectorData(pluginName);
            if (CollectionUtils.isEmpty(selectors)) {
                // 如果选择器为空, 首先判断是否为waf插件(防火墙),再判断是否为divide, dubbo, spring-cloud,
                // 只要是其中一种,就直接执行插件的处理方法
                return handleSelectorIsNull(pluginName, exchange, chain);
            }
            // 更具响应的uri和selector进行过滤,拿到对应的selectorData,如果有多条直接默认第一条选择器
            final SelectorData selectorData = matchSelector(exchange, selectors);
            if (Objects.isNull(selectorData)) {
                return handleSelectorIsNull(pluginName, exchange, chain);
            }
            selectorLog(selectorData, pluginName);
            // 通过选择器ID拿到路由Id
            final List<RuleData> rules = BaseDataCache.getInstance().obtainRuleData(selectorData.getId());
            // 如果规则为空,判断插件是否是waf,divide,dubbo,spring cloud,如果是的话直接执行插件操作
            // 如果不是上述插件,将包 "Can not match plugin" 的异常
            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);
            }
            // 如果规则为空,判断插件是否是waf,divide,dubbo,spring cloud,如果是的话直接执行插件操作
            // 如果不是上述插件,将包 "Can not match plugin" 的异常
            if (Objects.isNull(rule)) {
                return handleRuleIsNull(pluginName, exchange, chain);
            }
            ruleLog(rule, pluginName);
            // 执行插件操作
            return doExecute(exchange, chain, selectorData, rule);
        }
        return chain.execute(exchange);
    }

猜你喜欢

转载自blog.csdn.net/qq_35115942/article/details/112856469