ITKeyword - 技术文章推荐分享

首页 > dubbo注册部分源码分析与我思考的miniDubbo结构

dubbo注册部分源码分析与我思考的miniDubbo结构

标签: dubbo, 源码, java,

相关推荐:Dubbo源码分析1

这是本人对于Dubbo源码分析的系列一,没有 说明Dubbo是什么,不清楚请先了解,此处只是为了给自己做个笔记,也给正在学习Dubbo的同学一些借鉴,后期会继续奉上所有关于Dubbo的逻辑分 析,包括Dubbo简介、初始化与请求细节、注册中心、监控中心、治理中心等(由

前面分别写了二篇文章,介绍dubbo的源码与模拟现场场景的结构与调用分析。目前还缺少注册与统计模块的分析,所以又抽空看了一下注册部分,并思考如何在特定场景下实现一个简单的soa的管理的minidubbo。

说到分析源码,我一般先网上找几篇看看,可是总看的云里雾里,而且dubbo升级后有些变化,所以还是自己硬啃一下。时间仓促欢迎斧正,我看的源码是2.5.3。 一、dubbo注册分析

网上的源码最大的问题是没有一个完整的思维模型引导,所以我先介绍我所了解的注册部分的思维模型。注册就相当于一个购物平台,总不能买卖双方总是直接调用吧,所以可以这么理解:调用方如果配置注册中心,就注册自己,并从平台查询,可以得到自己想到的实现服务的被调用方地址,这个是订阅过程,会不断返回一些被调用方的URL,而这些个URL就是真正的被调用方了,存起来并按一定负载规则选择一个当成直接调用就OK了。而被调用方也是注册自己,并从平台得到..些URL重新暴露。(这里没明白为要得到那些URL并重新doChangeLocalExport,反正也是订阅并传入一个监听器,但不影响整体理解)。而注册时的数据存放可以是zookeeper,radis,也可以是数据库,但注册,订阅等业务逻辑都是调用端与被调用端来实现的。

调用方的一个接口,从注册中心找到多个实现

当调用端直接配置被调用端时,用dubboProtocol的refer方法就生成invoker,而当配置为注册中心时,调用方的接口就要按registryProtocol提供的refer生成invoker,而且一个接口配置了多个注册中心,并且有多个提供方时,那就比较麻烦了。我买一件商品,那么多商家提供,那当然弱水三千只取一瓢了,但可以随机,也可以选择最便宜的。

registryProtocol与RegistryDirectory是两个核心的业务逻辑类,另外根据注册中心的不同还有些不同的注册器与注册器工厂,比如zookeeper,radis的。

我们看到,registryProtocol做refer的时候得到相应的注册器,比如zookeeper的,再做dorefer的时候三件事,先是注册registry.register(*),再是订阅,订阅就是我扔个回调对象给你,你有事了通知回调对象就行了,我就知道了。代码就是directory.subscribe(*)内部是registry.subscribe(url, this);。最后就是cluster.join(directory);

总结一下,得到注册中心的地址后,调用方用zookeeper注册器来注册一下,并传入一个对象RegistryDirectory向注册器订阅可用的url,注册器会有一个线程不断的查找zookeeper的节点得到可用的url来通知RegistryDirectory。RegistryDirectory拿到这些url就一个个得到invokers,这些invokers的持有者RegistryDirectory会生成一个实现了invoker的代理对象。而客户端以后就调用这个invoker的代理对象了,代理对象会用策略从一堆真正的invoker中拿一个来用的。 --------------------------《代码》-------------------------- 拿到一个注册中心的真正一堆url后,转化成一堆invoker的重要语句如下: //把订阅的url转化为invoker就是RegistryDirectory类中的refreshInvoker方法中的这句 Map<String, Invoker<T>> newUrlInvokerMap = toInvokers(invokerUrls) ; //转化过程就是用注册中心告诉你的真正的一堆url,用各自的协议来refer一下,生成一堆invoker。 invoker = new InvokerDelegete<T>(protocol.refer(serviceType, url), url, providerUrl); invoker代理对象找出一个invoker来用就是FailoverClusterInvoker中的下面这句: Invoker<T> invoker = select(loadbalance, invocation, copyinvokers, invoked); ----------------------------《END》------------------------ 疑问是:有几个注册中心,如果每个中心都查到有实现,那就有几个代理对象吗?那又多一层选择吗?一个调用先选择一个代理对象,代理对象中又选择出一个真正的invoker?还是把这些全部合并到一起了?这个细节还没有看。发现ReferenceConfig中有:invoker = cluster.join(new StaticDirectory(u, invokers));也是集群策略。 解答:今天又看了一会代码,明白了。当我们从afterPropertiesSet()开始追踪调用端对象的诞生时,直到看这

相关推荐:dubbo源码分析系列(4)dubbo通信设计

2 NIO通信层的抽象目前dubbo已经集成的有netty、mina、grizzly。先来通过案例简单了解下netty、mina编程(grizzly没有了解过)2.1 netty和mina的简单案例netty原本是jboss开发的,后来单独出来了,所以会有两种版本就是org.jboss.netty和io.netty两

个方法createProxy(Map<String, String> map),最终生成调用端的代理对象。 --------------------------《代码》-------------------------- //加载所有的注册中心地址 List<URL> us = loadRegistries(false); ... for (URL url : urls) { //每一个注册中心生成一个invoker,放在一起。注意一个注册中心生成的是一个集群failover的invoker。

invokers.add(refprotocol.refer(interfaceClass, url)); } ... //把每个注册中心的invoker再组成一个集群。这里不是failoverCluster了,是AvailableCluster了。 invoker = cluster.join(new StaticDirectory(u, invokers)); ------------------------------《END》-------------------------

就是说:一个注册中心得到的是集群,而多个注册中心是集群的集群。但是集群策略不一样。其实之前已猜测到了,只是对refprotocol有点困惑,所有的注册中心怎么用同一个变量refprotocol来refer呢?不同的注册中心协议不一样啊,有zookeeper,radis等。当然我知道是spi进来的,但总不能用一个变量吧。突然想起之前的文章中我还分析过spi的特别之处。阿里的spi得到的是一个适配器,是用生成代码编译方式的,具体适配是那个类,要根据参数定的。那就对了,注册中心的URL是不一样的,所以得到不同的类。

此刻又一想,不对,注册协议只有一个RegistryProtocol,不同的注册中心导致注册协议refer时用的注册器不一样。真是忙了几天别的,思维有点断,还好理顺了! 二、注册中的集群策略与负载均衡算法汇总与应用场景 DUBBO中的宝贝越挖越多,这也是发现的一批重要知识点,在分布式环境中用的非常多,都总结到一起了,可以对比学习使用。 1.负载均衡算法--只要有集群都需要,在电商业务中,比如对不同级别的用户,权重也可能有差别,很多地方用的到。 1.1 RandomLoadBalance:

如果权重一样,就是简单的random,如果有权重,那把权重累加起来,从中得到一个随机数,在循环中不断累减随机数,如果出现负数就是要的值。这个算法没有去找证明,但我相信没问题,碰到了直接用。 1.2 ConsistentHashLoadBalance:

利用TreeMap实现的一致性HASH算法 1.3 RoundRobinLoadBalance:即轮询调度算法。比如有ABCD四个invoker,依次调用ABCD ABCD ABCD ABCD A...。如果加上权重稍微复杂一点,比如权重AC是2,BD是1,那次序是:ABCDAC ABCDAC ABCDAC.....。 2.集群策略 2.1 AvailableCluster:这个简单,从invokers中随便拿一个isAvailable()的invoker.拿的时候不需要负载均衡策略。 2.2 FailoverCluster:从invokers中按照负载均衡策略拿出来,可用就OK。不可用的话循环拿其它没拿过的。通用用于读操作,这个失败了换下一个。 FailfastCluster:从invokers中按照负载均衡策略拿出来一个,就用它了。不行就抛出异常。常用于非幂等性的写操作。非幂等就是一次操作与多次操作结果不一样。 2.3 FailbackCluster:从invokers中按照负载均衡策略拿出来一个,如果执行不成功,那记录下来,产生一个定时线程不断的重试。一般用于消息通知。 2.4 ForkingCluster:从invokers中按照负载均衡策略拿出来多个来,谁先有结果就是谁,用线程池来执行,把结果写入一个LinkedBlockingQueue,如果都是异常,把最后一个异常写入。主线程等待一定时间后用poll来取第一个。

这是并行调用,只要一个成功即返回,通常用于实时性要求较高的操作,但需要浪费更多服务资源。 2.5 FailsafeCluster:有异常时,也返回一个正常的空对象new RpcResult()。这个是失败安全,出现异常时,直接忽略,通常用于写入审计日志等操作。 2.6 BroadcastCluster:广播方式,就是从invokers中循环执行所有的invoker。大家一个接一个都来做一遍调用。 三、我思考的miniDubbo结构:

感觉Dubbo比较庞大,我们的应用基本都是web应用,用户不多,都是内部比较安全,会相互调用,而且调用可以都是http,那能否针对这种情况写一个小的soa管理呢?主要是把已有的业务方便的包装成对外的服务,服务还可以统一注册并统计调用情况,时间与用量等。实际上调用方用http协议传方法名,参数和获得返回值,提供方就是找到实现类,反射调用一下。简单点,调用异常返回统一码。

相关推荐:[Java数据结构]从源码分析HashMap

HashMapHashMap和Hashtable的区别:Hashtable的大部分方法做了同步,HashMap没有,因此,HashMap不是线程安全的。Hashtable不允许key或者value使用null值,而HashMap可以。在内部算法上,它们对key的hash算法和hash值到内存索引的映射算法不同。

? 前面分别写了二篇文章,介绍dubbo的源码与模拟现场场景的结构与调用分析。目前还缺少注册与统计模块的分析,所以又抽空看了一下注册部分,并思考如何在特定场景下实现一个简单的soa的管理的mi...

------分隔线----------------------------