在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中设置的: