RM新时代网站-首页

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內(nèi)不再提示

Dubbo路由模塊及負載均衡的優(yōu)化手段

OSC開源社區(qū) ? 來源: vivo互聯(lián)網(wǎng)技術 ? 2023-11-02 09:56 ? 次閱讀

作者:vivo 互聯(lián)網(wǎng)中間件團隊- Wang Xiaochuang

本文主要介紹在vivo內(nèi)部針對Dubbo路由模塊及負載均衡的一些優(yōu)化手段,主要是異步化+緩存,可減少在RPC調(diào)用過程中路由及負載均衡的CPU消耗,極大提升調(diào)用效率。

一、概要

vivo內(nèi)部Java技術棧業(yè)務使用的是Apache Dubbo框架,基于開源社區(qū)2.7.x版本定制化開發(fā)。在海量微服務集群的業(yè)務實踐中,我們發(fā)現(xiàn)Dubbo有一些性能瓶頸的問題會極大影響業(yè)務邏輯的執(zhí)行效率,尤其是在集群規(guī)模數(shù)量較大時(提供方數(shù)量>100),路由及負載均衡方面有著較大的CPU消耗,從采集的火焰圖分析高達30%。為此我們針對vivo內(nèi)部常用路由策略及負載均衡進行相關優(yōu)化,并取得了較好的效果。接下來主要跟大家分析一下相關問題產(chǎn)生的根源,以及我們采用怎樣的方式來解決這些問題。(當前vivo內(nèi)部使用的Dubbo的主流版本是基于2.7.x進行相關定制化開發(fā)。)

二、背景知識

2.1 Dubbo客戶端調(diào)用流程

1.相關術語介紹

fc6a6922-78a4-11ee-939d-92fbcf53809c.png

2.主要流程

客戶端通過本地代理Proxy調(diào)用ClusterInvoker,ClusterInvoker從服務目錄Directory獲取服務列表后經(jīng)過路由鏈獲取新的服務列表、負載均衡從路由后的服務列表中根據(jù)不同的負載均衡策略選取一個遠端Invoker后再發(fā)起遠程RPC調(diào)用。

fc8083e2-78a4-11ee-939d-92fbcf53809c.png

2.2 Dubbo路由機制

Dubbo的路由機制實際是基于簡單的責任鏈模式實現(xiàn),同時Router繼承了Comparable接口,自定義的路由可以設置不同的優(yōu)先級進而定制化責任鏈上Router的順序。基于責任鏈模式可以支持多種路由策略串行執(zhí)行如就近路由+標簽路由,或條件路由+就近路由等,且路由的配置支持基于接口級的配置也支持基于應用級的配置。常見的路由方式主要有:就近路由,條件路由,標簽路由等。具體的執(zhí)行過程如下圖所示:

fca0573a-78a4-11ee-939d-92fbcf53809c.png

1. 核心類

Dubbo路由的核心類主要有:RouterChain、RouterFactory 與 Router 。

(1)RouterChain

RouterChain是路由鏈的入口,其核心字段有

invokers(List 類型)

初始服務列表由服務目錄Directory設置,當前RouterChain要過濾的Invoker集合

builtinRouters(List類型)

當前RouterChain包含的自動激活的Router集合

routers(List類型)

包括所有要使用的路由由builtinRouters加上通過addRouters()方法添加的Router對象

RouterChain核心邏輯

public class RouterChain {


    // 注冊中心最后一次推送的服務列表
    private List> invokers = Collections.emptyList();


    // 所有路由,包括原生Dubbo基于注冊中心的路由規(guī)則如“route://” urls .
    private volatile List routers = Collections.emptyList();


    // 初始化自動激活的路由
    private List builtinRouters = Collections.emptyList();
  
   private RouterChain(URL url) {
    //通過ExtensionLoader加載可自動激活的RouterFactory
        List extensionFactories = ExtensionLoader.getExtensionLoader(RouterFactory.class)
                .getActivateExtension(url, ROUTER_KEY);
    // 由工廠類生成自動激活的路由策略
        List routers = extensionFactories.stream()
                .map(factory -> factory.getRouter(url))
                .collect(Collectors.toList());


        initWithRouters(routers);
    }
  
    // 添加額外路由
    public void addRouters(List routers) {
        List newRouters = new ArrayList<>();
        newRouters.addAll(builtinRouters);
        newRouters.addAll(routers);
        Collections.sort(newRouters, comparator);
        this.routers = newRouters;
    }
  
   public List> route(URL url, Invocation invocation) {
        List> finalInvokers = invokers;
    // 遍歷全部的Router對象,執(zhí)行路由規(guī)則
        for (Router router : routers) {
            finalInvokers = router.route(finalInvokers, url, invocation);
        }
        return finalInvokers;
    }
}

(2)RouterFactory為Router的工廠類

RouterFactory接口定義

@SPI
public interface RouterFactory {


    @Adaptive("protocol")
    Router getRouter(URL url);
}

(3)Router

Router是真正的路由實現(xiàn)策略,由RouterChain進行調(diào)用,同時Router繼承了Compareable接口,可以根據(jù)業(yè)務邏輯設置不同的優(yōu)先級。

Router主要接口定義

public interface Router extends Comparable {


   
    /**
     *
     * @param invokers   帶過濾實例列表
     * @param url        消費方url
     * @param invocation 會話信息
     * @return routed invokers
     * @throws RpcException
     */
     List> route(List> invokers, URL url, Invocation invocation) throws RpcException;




    /**
     * 當注冊中心的服務列表發(fā)現(xiàn)變化,或有動態(tài)配置變更會觸發(fā)實例信息的變化
     * 當時2.7.x的Dubbo并沒有真正使用這個方法,可基于此方法進行路由緩存
     * @param invokers invoker list
     * @param       invoker's type
     */
    default  void notify(List> invokers) {


    }


}

2.同機房優(yōu)先路由的實現(xiàn)

為方便大家了解路由的實現(xiàn),給大家展示一下就近路由的核心代碼邏輯

public  List> route(List> invokers, URL consumerUrl, Invocation invocation) throws RpcException {
        if (!this.enabled) {
            return invokers;
        }


      
    // 獲取本地機房信息
        String local = getSystemProperty(LOC);
        if (invokers == null || invokers.size() == 0) {
            return invokers;
        }
        List> result = new ArrayList>();
        for (Invoker invoker: invokers) {
      // 獲取與本地機房一致的invoker并加入列表中
            String invokerLoc = getProperty(invoker, invocation, LOC);
            if (local.equals(invokerLoc)) {
                result.add(invoker);
            }
        }


        if (result.size() > 0) {
            if (fallback){
                // 開啟服務降級,available.ratio = 當前機房可用服務節(jié)點數(shù)量 / 集群可用服務節(jié)點數(shù)量
                int curAvailableRatio = (int) Math.floor(result.size() * 100.0d / invokers.size());
                if (curAvailableRatio <= availableRatio) {
                    return invokers;
                }
            }


            return result;
        } else if (force) {
            return result;
        } else {
            return invokers;
        }


    }

2.3 Dubbo負載均衡

Dubbo的負載均衡實現(xiàn)比較簡單基本都是繼承抽象類進行實現(xiàn),主要作用就是根據(jù)具體的策略在路由之后的服務列表中篩選一個實例進行遠程RPC調(diào)用,默認的負載均衡策略是隨機。

整體類圖如下所示:

fcaba144-78a4-11ee-939d-92fbcf53809c.jpg

LoadBalance接口定義

@SPI(RandomLoadBalance.NAME)
public interface LoadBalance {


    /**
     * 從服務列表中篩選一個.
     *
     * @param invokers   invokers.
     * @param url        refer url
     * @param invocation invocation.
     * @return selected invoker.
     */
    @Adaptive("loadbalance")
     Invoker select(List> invokers, URL url, Invocation invocation) throws RpcException;


}

隨機負載均衡核心代碼解析

   // 預熱過程權重計算
   static int calculateWarmupWeight(int uptime, int warmup, int weight) {
        int ww = (int) (uptime / ((float) warmup / weight));
        return ww < 1 ? 1 : (Math.min(ww, weight));
    }


int getWeight(Invoker invoker, Invocation invocation) {
       int weight;
       URL url = invoker.getUrl();
       // 多注冊中心場景下的,注冊中心權重獲取
       if (UrlUtils.isRegistryService(url)) {
           weight = url.getParameter(REGISTRY_KEY + "." + WEIGHT_KEY, DEFAULT_WEIGHT);
       } else {
           weight = url.getMethodParameter(invocation.getMethodName(), WEIGHT_KEY, DEFAULT_WEIGHT);
           if (weight > 0) {
               // 獲取實例啟動時間
               long timestamp = invoker.getUrl().getParameter(TIMESTAMP_KEY, 0L);
               if (timestamp > 0L) {
                   long uptime = System.currentTimeMillis() - timestamp;
                   if (uptime < 0) {
                       return 1;
                   }
                   // 獲取預熱時間
                   int warmup = invoker.getUrl().getParameter(WARMUP_KEY, DEFAULT_WARMUP);
                   if (uptime > 0 && uptime < warmup) {
                       weight = calculateWarmupWeight((int)uptime, warmup, weight);
                   }
               }
           }
       }
       return Math.max(weight, 0);
   }


@Override
    protected  Invoker doSelect(List> invokers, URL url, Invocation invocation) {
        // Number of invokers
        int length = invokers.size();
        // Every invoker has the same weight?
        boolean sameWeight = true;
        // the weight of every invokers
        int[] weights = new int[length];
        // the first invoker's weight
        int firstWeight = getWeight(invokers.get(0), invocation);
        weights[0] = firstWeight;
        // The sum of weights
        int totalWeight = firstWeight;
        for (int i = 1; i < length; i++) {
            int weight = getWeight(invokers.get(i), invocation);
            // save for later use
            weights[i] = weight;
            // Sum
            totalWeight += weight;
            if (sameWeight && weight != firstWeight) {
                sameWeight = false;
            }
        }
        if (totalWeight > 0 && !sameWeight) {
            // If (not every invoker has the same weight & at least one invoker's weight>0), select randomly based on totalWeight.
            int offset = ThreadLocalRandom.current().nextInt(totalWeight);
            // Return a invoker based on the random value.
            for (int i = 0; i < length; i++) {
                offset -= weights[i];
                if (offset < 0) {
                    return invokers.get(i);
                }
            }
        }
        // If all invokers have the same weight value or totalWeight=0, return evenly.
        return invokers.get(ThreadLocalRandom.current().nextInt(length));
    }

預熱解釋

預熱是為了讓剛啟動的實例流量緩慢增加,因為實例剛啟動時各種資源可能還沒建立連接,相關代碼可能還是處于解釋執(zhí)行,仍未變?yōu)镴IT執(zhí)行,此時業(yè)務邏輯較慢,不應該加載過大的流量,否則有可能造成較多的超時。Dubbo默認預熱時間為10分鐘,新部署的實例的流量會在預熱時間段內(nèi)層線性增長,最終與其他實例保持一致。Dubbo預熱機制的實現(xiàn)就是通過控制權重來實現(xiàn)。如默認權重100,預熱時間10分鐘,則第一分鐘權重為10,第二分鐘為20,以此類推。

具體預熱效果圖如下:

fcc7b19a-78a4-11ee-939d-92fbcf53809c.png

三、問題分析

使用Dubbo的業(yè)務方反饋,他們通過火焰圖分析發(fā)現(xiàn)Dubbo的負載均衡模塊+路由模塊占用CPU超過了30%,框架層面的使用率嚴重影響了業(yè)務邏輯的執(zhí)行效率急需進行優(yōu)化。通過火焰圖分析,具體占比如下圖,其中該機器在業(yè)務忙時的CPU使用率在60%左右,閑時在30%左右。

fce07ff4-78a4-11ee-939d-92fbcf53809c.png

通過火焰圖分析,負載均衡主要的消耗是在 getWeight方法。

fcee495e-78a4-11ee-939d-92fbcf53809c.png

路由的主要消耗是在route方法:

同機房優(yōu)先路由

fd10675a-78a4-11ee-939d-92fbcf53809c.png

接口級標簽路由+應用級標簽路由

fd2d9672-78a4-11ee-939d-92fbcf53809c.png

這些方法都有一個特點,那就是遍歷執(zhí)行。如負載均衡,針對每一個invoker都需要通過getWeight方法進行權重的計算;就近路由的router方法對于每一個invoker都需要通過url獲取及機房信息進行匹配計算。

我們分析一下getWeight及router時間復雜度,發(fā)現(xiàn)是O(n)的時間復雜度,而且路由是由路由鏈組成的,每次每個 Router的route方法調(diào)用邏輯都會遍歷實例列表,那么當實例列表數(shù)量過大時,每次匹配的計算的邏輯過大,那么就會造成大量的計算成本,導致占用大量cpu,同時也導致路由負載均衡效率低下。

綜上所述,罪惡的的根源就是遍歷導致的,當服務提供方數(shù)量越多,影響越大。

四、優(yōu)化方案

知道了問題所在,我們來分析一下是否有優(yōu)化空間。

4.1 路由優(yōu)化

1. 優(yōu)化一:關閉無效路由

通過火焰圖分析,我們發(fā)現(xiàn)有部分業(yè)務即使完全不使用應用級的標簽路由,原生的TagRouter也存在遍歷邏輯,原因是為了支持靜態(tài)的標簽路由,其實這部分的開銷也不少,那對于根本不會使用應用級標簽路由的可以手動進行關閉。關閉方式如下:

客戶端統(tǒng)一關閉

dubbo.consumer.router=-tag

服務級別關閉

注解方式:

@DubboReference(parameters = {"router","-tag"})

xml方式:

2. 優(yōu)化二:提前計算路由結果并進行緩存

每次路由目前都是進行實時計算,但是在大多數(shù)情況下,我們的實例列表是穩(wěn)定不變的,只有在發(fā)布窗口或配置變更窗口內(nèi)實例列表才會發(fā)生變更,那我們是否可以考慮緩存呢。如就近路由,可以以機房為key進行機房實例的全量緩存。針對接口級標簽路由可以緩存不同標簽值指定的實例信息。

我們知道路由的執(zhí)行過程是責任鏈模式,每一個Router的實例列表入?yún)嶋H上是一個Router的結果,可參考公式:target = rn(…r3(r2(r1(src))))。那么所有的路由可以基于注冊中心推送的原始服務列表進行路由計算并緩存,然后不同的路由結果相互取交集就能得到最終的結果,當實例信息發(fā)生變更時,緩存失效并重新計算。

3. 緩存更新時機

當注冊中心或者動態(tài)配置有變更時,相關通知會給到服務目錄Directory,Directory收到通知后會重新創(chuàng)建服務列表,并把服務列表同步到路由鏈RouterChain,RouterChain再按順序通知其鏈上的Router,各個Router再進行緩存清除并重新進行路由結果的計算及進行緩存。相關時序圖如下所示:

fd4c288a-78a4-11ee-939d-92fbcf53809c.png

4. 具體路由流程

進入具體路由方法時,先判斷是否存在緩存的路由值,且緩存值的epoch必須與上一個路由的epoch需一致,此時緩存才生效,然后緩存值與上個Router的結果取交集。

如果不存在緩存或epoch不一致則重新進行實時的路由計算。

fd61c2d0-78a4-11ee-939d-92fbcf53809c.jpg

引入epoch的原因主要是保證各個路由策略緩存信息的一致性,保證所有的緩存計算都是基于同一份原始數(shù)據(jù)。當實例信息發(fā)生變更時,epoch會自動進行更新。

5. BitMap引入

上文我們說到,不同的路由策略之間的結果是取交集的,然后最終的結果才送入負載均衡流程。那如何在緩存的同時,加快交集的計算呢。答案就是基于位圖:BitMap。

BitMap的基本原理就是用一個bit位來存放某種狀態(tài),適用于大規(guī)模數(shù)據(jù)的查找及位運算操作。如在路由場景,先基于全量的推送數(shù)據(jù)進行計算緩存。如果某個實例被路由選中,則其值為1,若兩個路由的結果要取交集,那直接對BitMap進行"&"運行即可。

全量緩存示意圖:

fd7666fe-78a4-11ee-939d-92fbcf53809c.jpg

路由交集計算示步驟:

按照路由鏈依次計算,

tagRouter->vivoTag->vivoNearestRouter

(1)tagRouter計算邏輯:

按照Invocation計算出目標的Tag,假設是tag1

然后從緩存Cache根據(jù)key:tag1,取出對應的targetAddrPool

將原始傳入的addrPool

與targetAddrPool

得到結果resultAddrPool

將resultAddrPool傳入vivoTagRouter

(2)vivoTag計算邏輯:

按照Invocation計算出目標的Tag,假設是tabB

然后從緩存Cache根據(jù)key:tag1,取出對應的targetAddrPool

將上一次傳入的addrPool

與targetAddrPool

得到結果resultAddrPooll

將resultAddrPool傳入

vivoNearestRouter

(3)vivoNearestRouter計算邏輯

從環(huán)境變量取出當前機房,假設是bj01

然后從緩存Cache根據(jù)key:bj01,取出對應的targetAddrPool

將上一次傳入的addrPool

與targetAddrPool

取出resultAddrPool

將上一次傳入的addrPool

與targetAddrPool

得到結果resultAddrPool

將resultAddrPool為最終路由結果,傳遞給LoadBalance

fd94ea52-78a4-11ee-939d-92fbcf53809c.png

6. 基于緩存的同機房優(yōu)先路由源碼解析

緩存刷新

 /**
     * Notify router chain of the initial addresses from registry at the first time.
     * Notify whenever addresses in registry change.
     */
    public void setInvokers(List> invokers) {
    // 創(chuàng)建帶epoch的BitList
        this.invokers = new BitList>(invokers == null ? Collections.emptyList() : invokers,createBitListEpoch());
        routers.forEach(router -> router.notify(this.invokers));
    }

同機房優(yōu)先路由源碼解讀

public  List> route(List> invokers, URL consumerUrl, Invocation invocation) throws RpcException {
        …………//省略非核心代碼
        BitList> bitList = (BitList>) invokers;
    //獲取路由結果
        BitList> result = getNearestInvokersWithCache(bitList);
        if (result.size() > 0) {
            if (fallback) {
                // 開啟服務降級,available.ratio = 當前機房可用服務節(jié)點數(shù)量 / 集群可用服務節(jié)點數(shù)量
                int curAvailableRatio = (int) Math.floor(result.size() * 100.0d / invokers.size());
                if (curAvailableRatio <= availableRatio) {
                    return invokers;
                }
            }


            return result;
        } else if (force) {
            return result;
        } else {
            return invokers;
        }


    }   
   /**
     * 獲取緩存列表
     * @param invokers
     * @param 
     * @return
     */
    private  BitList> getNearestInvokersWithCache(BitList> invokers) {
        ValueWrapper valueWrapper = getCache(getSystemProperty(LOC));
        // 是否存在緩存
        if (valueWrapper != null) {
            BitList> invokerBitList = (BitList>) valueWrapper.get();
            // 緩存的epoch與源列表是否一致
            if (invokers.isSameEpoch(invokerBitList)) {
                BitList> tmp = invokers.clone();
                // 結果取交集
                return tmp.and(invokerBitList);
            }
        }
        // 緩存不存在 實時計算放回
        return getNearestInvokers(invokers);
    }
  
  /**
     * 新服務列表通知
     * @param invokers
     * @param 
     */
 @Override
    public  void notify(List> invokers) {
        clear();
        if (invokers != null && invokers instanceof BitList) {
            BitList> bitList = (BitList>) invokers;
      // 設置最后一次更新的服務列表
            lastNotify = bitList.clone();
            if (!CollectionUtils.isEmpty(invokers) && this.enabled) {
        // 獲取機房相同的服務列表并進行緩存
                setCache(getSystemProperty(LOC), getNearestInvokers(lastNotify));
            }
        }
    }

4.2 負載均衡優(yōu)化

1.優(yōu)化一

針對getWeight方法,我們發(fā)現(xiàn)有部分業(yè)務邏輯較為消耗cpu,但是在大多數(shù)場景下業(yè)務方并不會使用到,于是進行優(yōu)化。

getWeight方法優(yōu)化

優(yōu)化前:
//這里主要要用多注冊中心場景下,注冊中心權重的獲取,絕大多數(shù)情況下并不會有這個邏輯
 if (UrlUtils.isRegistryService(url)) {
           weight = url.getParameter(REGISTRY_KEY + "." + WEIGHT_KEY, DEFAULT_WEIGHT);
       }  
優(yōu)化后:
 if (invoker instanceof ClusterInvoker && UrlUtils.isRegistryService(url)) {
            weight = url.getParameter(REGISTRY_KEY + "." + WEIGHT_KEY, DEFAULT_WEIGHT);
   }

2.優(yōu)化二

遍歷是罪惡的源泉,而實例的數(shù)量決定這罪惡的深淺,我們有什么辦法減少負載均衡過程中的遍歷呢。一是根據(jù)group及version劃分不同的集群,但是這需要涉及到業(yè)務方代碼或配置層面的改動,會帶來額外的成本。所以我們放棄了。

二是沒有什么是加一層解決不了的問題,為了盡量減少進入負載均衡的節(jié)點數(shù)量,考慮新增一個墊底的路由策略,在走完所有的路由策略后,若節(jié)點數(shù)量>自定義數(shù)量后,進行虛擬分組,虛擬分組的策略也可進行自定義,然后隨機篩選一組進入負載均衡。此時進入負載均衡的實例數(shù)量就會有倍數(shù)的下降。

需要注意的是分組路由必須保證是在路由鏈的最后一環(huán),否則會導致其他路由計算錯誤。

fdb3db2e-78a4-11ee-939d-92fbcf53809c.png

分組路由示意

  /**
     * 
     * @param invokers 待分組實例列表
     * @param groupNum 分組數(shù)量
     * @param 
     * @return
     */
    public  List> doGroup(List> invokers, int groupNum) {
        int listLength = invokers.size() / groupNum;
        List> result = new ArrayList<>(listLength);
        int random = ThreadLocalRandom.current().nextInt(groupNum);
        for (int i = random; i < invokers.size(); i = i + groupNum) {
            result.add(invokers.get(i));
        }
        return result;
    }

五、優(yōu)化效果

針對優(yōu)化前和優(yōu)化后,我們編寫Demo工程分別壓測了不配置路由/配置就近+標簽路由場景。Provider節(jié)點梯度設置100/500/1000/2000/5000,TPS在1000左右,記錄了主機的cpu等性能指標,并打印火焰圖。發(fā)現(xiàn),配置路由后,采用相同并發(fā),優(yōu)化后的版本tps明顯高于優(yōu)化前版本,且新版本相較于沒有配置路由時tps顯著提高,下游節(jié)點數(shù)大于2000時,tps提升達到100%以上,下游節(jié)點數(shù)越多,AvgCpu優(yōu)化效果越明顯,并且路由及負載均衡CPU占比明顯更低,詳細數(shù)據(jù)可見下表:

fdce5094-78a4-11ee-939d-92fbcf53809c.png

fde739a6-78a4-11ee-939d-92fbcf53809c.png

備注:-tag,表示顯式禁用原生Dubbo應用級標簽路由。該路由默認開啟。

六、總結

經(jīng)過我們關閉不必要的路由邏輯、對路由緩存+異步化計算、新增分組路由等優(yōu)化后,Dubbo在負載均衡及路由模塊整體的性能有了顯著的提升,為業(yè)務方節(jié)省了不少CPU資源。在正常業(yè)務場景下當提供方數(shù)量達到2000及以上時,tps提升可達100%以上,消費方平均CPU使用率下降約27%,且提供方數(shù)量越多優(yōu)化效果越明顯。但是我們也發(fā)現(xiàn)當前的隨機負載均衡依然還是會消耗一定的CPU資源,且只能保證流量是均衡的。當前我們的應用基本部署在虛擬機及容器上。這兩者均存在超賣的狀況,且同等配置的宿主機性能存在較大差異等問題。最終會導致部分請求超時、無法最大化利用提供方的資源。我們下一步將會引入Dubbo 3.2的自適應負載均衡并進行調(diào)優(yōu)減少其CPU使用率波動較大的問題,其次我們自身也擴展了基于CPU負載均衡的單一因子算法,最終實現(xiàn)不同性能的機器CPU負載趨于均衡,最大程度發(fā)揮集群整體的性能。

審核編輯:湯梓紅
聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權轉載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學習之用,如有內(nèi)容侵權或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • cpu
    cpu
    +關注

    關注

    68

    文章

    10854

    瀏覽量

    211568
  • 路由
    +關注

    關注

    0

    文章

    278

    瀏覽量

    41834
  • 負載均衡
    +關注

    關注

    0

    文章

    110

    瀏覽量

    12364
  • vivo
    +關注

    關注

    12

    文章

    3303

    瀏覽量

    63254
  • Dubbo
    +關注

    關注

    0

    文章

    19

    瀏覽量

    3177

原文標題:Dubbo路由及負載均衡性能優(yōu)化

文章出處:【微信號:OSC開源社區(qū),微信公眾號:OSC開源社區(qū)】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦

    路由負載均衡怎么配置

    路由負載均衡是一種重要的網(wǎng)絡技術,它能夠?qū)⒍鄠€網(wǎng)絡連接的流量分配到多個路由器上,以提高網(wǎng)絡的性能和穩(wěn)定性。本文將詳細介紹路由
    的頭像 發(fā)表于 12-13 11:17 ?3313次閱讀

    聊聊Dubbo - Dubbo可擴展機制實戰(zhàn)

    。RandomLoadBalance.NAME是一個常量,值是"random",是一個隨機負載均衡的實現(xiàn)。 random的定義在配置文件META-INF/dubbo
    發(fā)表于 06-04 17:33

    Dubbo開源現(xiàn)狀與未來規(guī)劃

    、多機房路由、灰度路由,以及更豐富的負載均衡策略。再往上通過元數(shù)據(jù)的優(yōu)化,我們可以更清晰的分開注冊層和配置層,從而可以在注冊層加入更多的對微
    發(fā)表于 07-05 15:21

    Dubbo Cloud Native 之路的實踐與思考

    Dubbo “隨機“、”輪詢“ 以及 ”最少活躍調(diào)用數(shù)“ 負載均衡算法中均體現(xiàn)。以上討論的兩種框架均屬于 Java 實現(xiàn),而中間的 Kong 則是更為通用的實現(xiàn),通常它作為 API 服務網(wǎng)關,后面
    發(fā)表于 07-05 16:05

    考慮負載均衡的多下一跳路由自愈方法

    考慮負載均衡的多下一跳路由自愈方法_陳天平
    發(fā)表于 01-03 18:00 ?0次下載

    HBase負載均衡分析及優(yōu)化策略

    HBase負載均衡分析及優(yōu)化策略_黃偉建
    發(fā)表于 01-03 17:41 ?0次下載

    路由負載均衡如何設置_路由負載均衡的模式詳解

    路由器中加入負載均衡技術已經(jīng)不是新鮮事。那么現(xiàn)在已經(jīng)衍生出很多種路由負載模式,不同的模式狀態(tài)下,可以完成不同的任務。而且模式間也可以進行轉
    發(fā)表于 01-01 19:43 ?3.9w次閱讀
    <b class='flag-5'>路由</b>器<b class='flag-5'>負載</b><b class='flag-5'>均衡</b>如何設置_<b class='flag-5'>路由</b>器<b class='flag-5'>負載</b><b class='flag-5'>均衡</b>的模式詳解

    Dubbo解析及原理淺析

    本文詳細闡述了Dubbo及其原理。Dubbo是一種分布式服務框架。dubbo除了可以提供服務之外,還可以實現(xiàn)軟負載均衡。它還提供了兩個功能M
    的頭像 發(fā)表于 02-07 15:57 ?2835次閱讀
    <b class='flag-5'>Dubbo</b>解析及原理淺析

    基于流量矩陣的負載均衡路由機制

    智慧協(xié)同網(wǎng)絡具有能夠?qū)崟r準確測算流量矩陣的特點。將流量矩陣作為約束,對負載均衡路由優(yōu)化問題進行建模,利用拉格朗日對偶方法,將原問題轉化為優(yōu)化
    發(fā)表于 02-12 11:18 ?0次下載

    Dubbo源代碼實現(xiàn)服務調(diào)用的動態(tài)代理和負載均衡

    我們知道,Dubbo將服務調(diào)用封裝成普通的Spring的Bean,于是我們可以像使用本地的Spring Bean一樣,來調(diào)用遠端的Dubbo服務,并有LoadBalance和Failover的功能
    發(fā)表于 03-12 14:35 ?0次下載

    解密負載均衡技術和負載均衡算法

    負載均衡器是一種軟件或硬件設備,它起到了將網(wǎng)絡流量分散到一組服務器的作用,可以防止任何一臺服務器過載。負載均衡算法就是負載
    的頭像 發(fā)表于 11-12 09:16 ?1126次閱讀

    浮動靜態(tài)路由負載均衡

    負載均衡:當數(shù)據(jù)有多條可選路徑前往同一目的網(wǎng)絡,可以通過配置相同優(yōu)先級和開銷的靜態(tài)路由來實現(xiàn)負載均衡,使得數(shù)據(jù)的傳輸
    的頭像 發(fā)表于 02-27 15:26 ?1412次閱讀
    浮動靜態(tài)<b class='flag-5'>路由</b>及<b class='flag-5'>負載</b><b class='flag-5'>均衡</b>

    如何確定適合的負載均衡比例

    路由器的負載均衡是一種應用于網(wǎng)絡中的技術,它可以平衡網(wǎng)絡流量的分配,提高網(wǎng)絡的性能和穩(wěn)定性。在配置路由器的負載
    的頭像 發(fā)表于 12-15 10:36 ?1560次閱讀

    華納云:什么是負載均衡?優(yōu)化資源利用率的策略

    負載均衡是現(xiàn)代計算機網(wǎng)絡架構中不可或缺的一部分,它通過智能分配請求和任務,確保系統(tǒng)資源的高效利用。本文將探討負載均衡的概念、工作原理、優(yōu)化
    的頭像 發(fā)表于 10-28 16:07 ?146次閱讀

    多鏈路負載均衡設置在哪里?

    多鏈路負載均衡設置涉及交換機、路由器和(可選)負載均衡器的設置。首先規(guī)劃網(wǎng)絡拓撲和IP地址,備份設備配置。然后,在交換機上配置VLAN和Tr
    的頭像 發(fā)表于 11-13 10:19 ?119次閱讀
    RM新时代网站-首页