Dubbo 代碼解析

spring集成

在dubbo-config下面的dubbo-config-spring模塊下面,有一個類DubboNamespaceHandler,它實現了Spring提供的接口NamespaceHandlerSupport;在該模塊的META-INF文件夾下有兩個文件: spring.handlersspring.schemas,這兩個文件裏面制定了dubbo的namespace的XSD文件的位置以及dubbo的namespace由DubboNamespaceHandler來處理解析。java

這些解析的config類 最終都繼承自 AbstractConfig。node

public class DubboNamespaceHandler extends NamespaceHandlerSupport {

  static {
      Version.checkDuplicate(DubboNamespaceHandler.class);
  }

  public void init() {
    registerBeanDefinitionParser("application", new DubboBeanDefinitionParser(ApplicationConfig.class, true));
    registerBeanDefinitionParser("module", new DubboBeanDefinitionParser(ModuleConfig.class, true));
    registerBeanDefinitionParser("registry", new DubboBeanDefinitionParser(RegistryConfig.class, true));
    registerBeanDefinitionParser("monitor", new DubboBeanDefinitionParser(MonitorConfig.class, true));
    registerBeanDefinitionParser("provider", new DubboBeanDefinitionParser(ProviderConfig.class, true));
    registerBeanDefinitionParser("consumer", new DubboBeanDefinitionParser(ConsumerConfig.class, true));
    registerBeanDefinitionParser("protocol", new DubboBeanDefinitionParser(ProtocolConfig.class, true));
    registerBeanDefinitionParser("service", new DubboBeanDefinitionParser(ServiceBean.class, true));
    registerBeanDefinitionParser("reference", new DubboBeanDefinitionParser(ReferenceBean.class, false));
    registerBeanDefinitionParser("annotation", new DubboBeanDefinitionParser(AnnotationBean.class, true));
  }

}

 

rpc協議: dubbo、hessian、http、redis、memcached、webservice、thrift、rest 等
web

ZookeeperRegistry 
doRegister 建立地址節點-> doSubscribe 發佈 -> 父類FailbackRegistry 的 notify 通告
redis

 

LoadBalance

@SPI(RandomLoadBalance.NAME)
public interface LoadBalance {
	/**
	 * select one invoker in list.
	 * 
	 * @param invokers invokers.
	 * @param url refer url
	 * @param invocation invocation.
	 * @return selected invoker.
	 */
    @Adaptive("loadbalance")
	<T> Invoker<T> select(List<Invoker<T>> invokers, URL url, Invocation invocation) throws RpcException;

}

通常在實際項目配置權重或負載均衡時不在代碼中寫死,使用默認配置。須要調節時經過dubbo管控臺上進行配置算法

<dubbo:service interface="..." loadbalance="roundrobin"/>

<dubbo:reference interface="..." loadbalance="roundrobin"/>

dubbo:service interface="...">
    <dubbo:methodname="..."loadbalance="roundrobin"/>
</dubbo:service>

<dubbo:reference interface="...">
    <dubbo:method name="..."loadbalance="roundrobin"/>
</dubbo:reference>

Random

隨機,按權重設置隨機機率。 默認策略
一個截面上碰撞的機率高,但調用量越大分佈越均勻,並且按機率使用權重後也比較均勻,有利於動態調整提供者權重。spring

  1. 獲取全部invokers的個數。
  2. 遍歷全部Invokers, 獲取計算每一個invokers的權重,並把權重累計加起來。每相鄰的兩個invoker比較他們的權重是否同樣,有一個不同說明權重不均等
  3. 總權重大於零且權重不均等的狀況下按總權重獲取隨機數offset = random.netx(totalWeight);遍歷invokers肯定隨機數offset落在哪一個片斷(invoker上)
  4. 權重相同或者總權重爲0, 根據invokers個數均等選擇

RoundRobin 

輪循,按公約後的權重設置輪循比率。數組

存在慢的提供者累積請求問題,好比:第二臺機器很慢,但沒掛,當請求調到第二臺時就卡在那,長此以往,全部請求都卡在調到第二臺上。
解決辦法 : 結合權重,把第二臺機(性能低的)的權重設置低一點app

  1. 獲取輪詢key  服務名+方法名; 獲取可供調用的invokers個數length; 設置最大權重的默認值maxWeight=0; 設置最小權重的默認值minWeight=Integer.MAX_VALUE;
  2. 遍歷全部Inokers,比較出得出maxWeight和minWeight
  3. 若是權重是不同的: 根據key獲取自增序列。自增序列加一與最大權重取模默認獲得currentWeigth; 遍歷全部invokers篩選出大於currentWeight的invokers。
  4. 設置可供調用的invokers的個數length
  5. 自增序列加一併與length取模,從invokers獲取invoker
protected <T> Invoker<T> doSelect(List<Invoker<T>> invokers, URL url, Invocation invocation) {
        String key = invokers.get(0).getUrl().getServiceKey() + "." + invocation.getMethodName();
        int length = invokers.size();
        int maxWeight = 0;
        int minWeight = Integer.MAX_VALUE;
        for (int i = 0; i < length; i++) {
            int weight = getWeight(invokers.get(i), invocation);
            maxWeight = Math.max(maxWeight, weight);
            minWeight = Math.min(minWeight, weight);
        }
        if (maxWeight > 0 && minWeight < maxWeight) { 
            AtomicPositiveInteger weightSequence = weightSequences.get(key);
            if (weightSequence == null) {
                weightSequences.putIfAbsent(key, new AtomicPositiveInteger());
                weightSequence = weightSequences.get(key);
            }
            int currentWeight = weightSequence.getAndIncrement() % maxWeight;
            List<Invoker<T>> weightInvokers = new ArrayList<Invoker<T>>();
            for (Invoker<T> invoker : invokers) { 
                if (getWeight(invoker, invocation) > currentWeight) {
                    weightInvokers.add(invoker);
                }
            }
            int weightLength = weightInvokers.size();
            if (weightLength == 1) {
                return weightInvokers.get(0);
            } else if (weightLength > 1) {
                invokers = weightInvokers;
                length = invokers.size();
            }
        }
        AtomicPositiveInteger sequence = sequences.get(key);
        if (sequence == null) {
            sequences.putIfAbsent(key, new AtomicPositiveInteger());
            sequence = sequences.get(key);
        }
        return invokers.get(sequence.getAndIncrement() % length);
    }

LeastActive

最少活躍調用數,相同活躍數的隨機,活躍數指調用先後計數差。負載均衡

使慢的提供者收到更少請求,由於越慢的提供者的調用先後計數差會越大dom

  1. 獲取可調用invoker的總個數;初始化最小活躍數,相同最小活躍的個數; 相同最小活躍數的下標數組 等等。
  2. 遍歷全部invokers, 獲取每一個invoker的獲取數active和權重。找出最小權重的invoker;若是有相同最小權重的inovkers, 將下標記錄到數組leastIndexs[]數組中; 累計全部的權重到totalWeight變量。
  3. 若是invokers的權重不相等且totalWeight大於0,按總權重隨機offsetWeight = random.nextInt(totalWeight),計算隨機值在哪一個片斷上並返回invoker。
  4. 若是invokers的權重相等或者totalWeight等於0,均等隨機

活躍計數的功能消費者是在ActiveLimitFilter中設置的:

ConsistentHash 

  • 一致性Hash,相同參數的請求老是發到同一提供者。
  • 當某一臺提供者掛時,本來發往該提供者的請求,基於虛擬節點,平攤到其它提供者,不會引發劇烈變更。
  • 算法參見:http://en.wikipedia.org/wiki/Consistent_hashing。
  • 缺省只對第一個參數Hash,若是要修改,請配置<dubbo:parameter key="hash.arguments" value="0,1" />
  • 缺省用160份虛擬節點,若是要修改,請配置<dubbo:parameter key="hash.nodes" value="320" />

相關文章
相關標籤/搜索