springcloud ,divide 插件跑通后,今天再 debug下 详细的流程。

这里可以看到 springCloud 插件,divide 插件都是在 webClientPlugin 插件之后执行的。

首先来看下插件的继承结构,soulPlugin 接口定义了这几个方法,而每个插件具体的类都实现了这几个方法。

AbstractSoulPlugin 实现的 execute 方法

   public Mono<Void> execute(final ServerWebExchange exchange, final SoulPluginChain chain) {
       String pluginName = named();
       //获取插件数据
       final PluginData pluginData = BaseDataCache.getInstance().obtainPluginData(pluginName);
       //插件开启才去找选择器和规则
       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;
           //匹配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(exchange, chain, selectorData, rule) 就是去对应插件执行它的 doExecute,这里看下 divide 插件的 doExecute 方法。

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;
        final DivideRuleHandle ruleHandle = GsonUtils.getInstance().fromJson(rule.getHandle(), DivideRuleHandle.class);
    	//从缓存中拿链接列表
        final List<DivideUpstream> upstreamList = UpstreamCacheManager.getInstance().findUpstreamListBySelectorId(selector.getId());
        if (CollectionUtils.isEmpty(upstreamList)) {
            log.error("divide upstream configuration error: {}", rule.toString());
            Object error = SoulResultWrap.error(SoulResultEnum.CANNOT_FIND_URL.getCode(), SoulResultEnum.CANNOT_FIND_URL.getMsg(), null);
            return WebFluxResultUtils.result(exchange, error);
        }
        final String ip = Objects.requireNonNull(exchange.getRequest().getRemoteAddress()).getAddress().getHostAddress();
    	//这里去找一条链接出来,配置了负载均衡的话,也是这里处理
        DivideUpstream divideUpstream = LoadBalanceUtils.selector(upstreamList, ruleHandle.getLoadBalance(), ip);
        if (Objects.isNull(divideUpstream)) {
            log.error("divide has no upstream");
            Object error = SoulResultWrap.error(SoulResultEnum.CANNOT_FIND_URL.getCode(), SoulResultEnum.CANNOT_FIND_URL.getMsg(), null);
            return WebFluxResultUtils.result(exchange, error);
        }
        // 构建 http url
        String domain = buildDomain(divideUpstream);
        String realURL = buildRealURL(domain, soulContext, exchange);
        exchange.getAttributes().put(Constants.HTTP_URL, realURL);
        // 把 timeout,url 设置在 exchange,传递给下一个插件
        exchange.getAttributes().put(Constants.HTTP_TIME_OUT, ruleHandle.getTimeout());
        exchange.getAttributes().put(Constants.HTTP_RETRY, ruleHandle.getRetry());
        return chain.execute(exchange);
    }

divide插件执行完后,会把 exchange 转给 下一插件,就这么一步步往下执行,直到最后一个插件 webClientResponsePlugin 处理返回数据。