zoukankan      html  css  js  c++  java
  • Soul 学习笔记---插件流程分析(十三)

    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 处理返回数据。

  • 相关阅读:
    javascript面向对象程序设计之浅谈2
    Sphinx学习之sphinx的安装篇
    IT人的职业生涯规划
    perconatoolkit系列之系统类工具的使用
    perconatoolkit系列之实用类工具使用
    查询ip归属地的shell脚本
    使用mysqlsla分析Mysql数据库日志
    MYSQL管理之主从同步管理
    MYSQL数据库管理之权限管理
    perconatoolkit系列之复制类工具使用
  • 原文地址:https://www.cnblogs.com/fightingting/p/14385280.html
Copyright © 2011-2022 走看看