在dubbo-config下面的dubbo-config-spring模塊下面,有一個類DubboNamespaceHandler,它實現了Spring提供的接口NamespaceHandlerSupport;在該模塊的META-INF文件夾下有兩個文件: spring.handlers和spring.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
@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>
隨機,按權重設置隨機機率。 默認策略
一個截面上碰撞的機率高,但調用量越大分佈越均勻,並且按機率使用權重後也比較均勻,有利於動態調整提供者權重。spring
輪循,按公約後的權重設置輪循比率。數組
存在慢的提供者累積請求問題,好比:第二臺機器很慢,但沒掛,當請求調到第二臺時就卡在那,長此以往,全部請求都卡在調到第二臺上。
解決辦法 : 結合權重,把第二臺機(性能低的)的權重設置低一點app
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); }
最少活躍調用數,相同活躍數的隨機,活躍數指調用先後計數差。負載均衡
使慢的提供者收到更少請求,由於越慢的提供者的調用先後計數差會越大dom
活躍計數的功能消費者是在ActiveLimitFilter中設置的: