Soul divide插件分析

在啟動Soul-bootstrap時可以看到下面這個日志輸出

 load plugin:[divide] [org.dromara.soul.plugin.divide.DividePlugin]

可以先閱讀DividePlugin類:


DividePlugin類繼承關(guān)系

閱讀源碼可知DividePlugin實現(xiàn)了AbstractSoulPlugin的 doExecute方法,而在AbstractSoulPlugin中doExecute被定義為抽象方法,在
execute()調(diào)用,這里用到了模板方法設(shè)計模式;
源碼如下:

 @Override
    public Mono<Void> execute(final ServerWebExchange exchange, final SoulPluginChain chain) {
        String pluginName = named();
        //(1)這個插件是否緩存
        final PluginData pluginData = BaseDataCache.getInstance().obtainPluginData(pluginName);
        if (pluginData != null && pluginData.getEnabled()) {
           //獲取SelectorData
            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;
            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);
           //模板方法,調(diào)用子類的實現(xiàn)
            return doExecute(exchange, chain, selectorData, rule);
        }

        return chain.execute(exchange);
    }

(1) 插件名稱命名規(guī)則:在PluginEnum中定義的枚舉
(2) chain.execute(exchange) 這邊采用了責(zé)任鏈的設(shè)計模式;

 @Override
        public Mono<Void> execute(final ServerWebExchange exchange) {
            return Mono.defer(() -> {
                if (this.index < plugins.size()) {
                    SoulPlugin plugin = plugins.get(this.index++);
                    Boolean skip = plugin.skip(exchange);
                    if (skip) {
                        return this.execute(exchange);
                    }
                    return plugin.execute(exchange, this);
                }
                return Mono.empty();
            });
        }
    }

接下來進入本篇的重點:doExecute(exchange, chain, selectorData, rule)

  @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;
        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);
        }
        // set the http url
        String domain = buildDomain(divideUpstream);
        String realURL = buildRealURL(domain, soulContext, exchange);
        exchange.getAttributes().put(Constants.HTTP_URL, realURL);
        // set the http timeout
        exchange.getAttributes().put(Constants.HTTP_TIME_OUT, ruleHandle.getTimeout());
        exchange.getAttributes().put(Constants.HTTP_RETRY, ruleHandle.getRetry());
        return chain.execute(exchange);
    }

關(guān)鍵看這一步:DivideUpstream divideUpstream = LoadBalanceUtils.selector(upstreamList, ruleHandle.getLoadBalance(), ip);
可以看出是負載均衡相關(guān)的
具體實現(xiàn)

 public static DivideUpstream selector(final List<DivideUpstream> upstreamList, final String algorithm, final String ip) {
        LoadBalance loadBalance = ExtensionLoader.getExtensionLoader(LoadBalance.class).getJoin(algorithm);
        return loadBalance.select(upstreamList, ip);
    }

默認的實現(xiàn)是:random
ExtensionLoader.getExtensionLoader(LoadBalance.class)通過SPI機制,LOADERS以class為key,緩存 ExtensionLoader實例;
getJoin(algorithm);在cachedInstances中以algorithm的值為key,獲取負載均衡器對象;


image.png

這個random在哪邊寫入?
頁面可以設(shè)置;(修改負載均衡策略)


image.png

這個負載均衡器也是采用了模板方法模式
image.png

只要實現(xiàn)doSelect()方法;

下一步目標:
自定義修改負載均衡器
嘗試接入dubbo

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,694評論 19 139
  • 本文作者:陳剛,叩丁狼高級講師。原創(chuàng)文章,轉(zhuǎn)載請注明出處。 本文章會通過斷點跟蹤的方式來解讀 Ribbon 源碼 ...
    叩丁狼教育閱讀 2,073評論 0 3
  • 內(nèi)存模型以及分區(qū) JVM分為虛擬機棧、堆、方法區(qū)、本地方法區(qū)堆,用來存放實例化對象、非static成員變量,屬于線...
    北京黃小胖閱讀 1,471評論 0 0
  • 本文主要分享SpringCloud中RestTemplate與@LoadBalanced的實現(xiàn)原理。源碼分析基于S...
    binecy閱讀 749評論 0 0
  • 本文主要分析 SpringCloud 中 Ribbon 負載均衡流程和原理。 SpringCloud版本為:Edg...
    Java大生閱讀 532評論 0 0

友情鏈接更多精彩內(nèi)容