图1
图1是服务引入的目标。
图2
图2 为服务引入的 dubbo :reference转化为 ReferenceBean对象。
图3
图3 为 服务引入整体流程。
最终目的: 根据服务名 去注册中心找到服务提供者的地址
1.首先从spring 中获取demoservice 对象,并且这个对象能够利用invoker(消费方) 调用提供者invoker对象。不可能直接返回一个invoker对象,然后在demoservice对象中强转。dubbo采用的方式是为这个接口生成一个实例对象,在这个实例对象中利用invoker远程调用 提供者,通过invoker可以获取相关的方法和参数通过远程传递给提供者。
2. 每一个服务提供者对应一个 invoker ,.多个服务提供者就会对应多个invoker。假设 一个消费者Invoker调用 调用一个服务提供者没有问题,返回一个invoker对象。如果一个 消费者Invoker调用多个提供者 怎么办法。dubbo采用的办法是把多个invoker合并成一个invoker来处理(具体处理逻辑是:根据服务名去注册中心获取多个服务地址,服务地址经过路由器过滤掉一部分地址,剩下的地址称为服务目录的invoker合并 ,真正调用的时候才选取一个再进行负载均衡和容错处理)。
图4
图4 注册中心和服务目录的关系。 服务目录 相当于本地缓存。服务目录通过从注册中心获取地址信息,需要经过路由过滤。服务目录监听注册中心。如果注册中心发生改变。服务目录页随之改变,保持一致性。
图5
图5 真正的服务引用开始。只有真正在获取的时候才会引用,即入口;有两种方式 一个xml
图6
255行 ,暴露时候有不在详解。 231行为真正的核心,init();
图7
139 行 返回的泛型。外面传的是什么里面返回的就是什么,见图8
图8
图 8 传的是DemoService, 返回的是就是Demoservice.
图9
图9位init()方法, 258行到305行 就是将dubbo xml各个节点封装到一个map中,完成属性覆盖。例如 不同的节点都配置了timeout,那么会以最后一个timeout 放入的时间为准。 305根据map创建代理类赋值给ref.
图10
图10为map详细信息。
图11
图11 326行 jvm的引入。
333行url 在xml
333行到348行 解析直连url。 以;分割遍历 url地址, 如果是registry开头的加上registry前缀。 把遍历后的地址加在urls中。那么这个ulrs 中包含http开头的url和registry开头的url.
349行到 363行从注册中心 获取的url地址信息,同上逻辑。
365行 只有一个的情况是registry或者http。url不配置值,直接用注册中心 如图14 的 执行366行.图15为url详情。
图12
图14
图15
图15 为registry 的详细地址, refer为外部配置
图16位reprotpcol 获取默认的实现类registryProtocol
图17
图18 依旧要经历 ProtocolListenerWrapper -> ProtocolFilterWrapper ->RegistryProtocol 依旧是协议是registry 跳过执行下一个。
图19 ProtocolListenerWrapper 执行refer 方法,如果是registry协议跳到 ProtocolFilterWrapper 执行 refer
图20执行RegistryProtocol的refer 方法。 设置默认registry 协议, 354行把url中registry=zookeeper 中的值zookeeper 取出来。更换协议为zookeeper.图21. 360行将url的refer_key对应的url转换为map 图23. 364 真正的执行duRefer方法。 regsitry就是携带zookeeper的registry, type 为 接口的全类名图26。url为全url. cuustrer 为合并后的invoker集合.
图21
图22
图23
图24
图25
图26
图 27
图27 375行 new RegistryDirectoy 一个服务目录。 这个服务目录实现通知接口 图28 ,376行更新zookeeper协议,377行设置协议的代理类。379行为传进来的map. 380行 更改协议为consumer协议。 382行和383行 往zookeeper注册中心注册consumer详细信息图31.
385行为构建路由链,图32和图33 。路由是过滤ip地址的。
2.6 有条件路由(图33 为控制台配置,图34为控制配置完后再zookeeper生成的详细路径,第一个标红的2.7后的路径信息,第二个标红的兼容2.6的路径信息);
2.7新增了标签路由(图35为控制台配置的标签路由和详细信息,图36位 标签信息在控制台配置完了在zookeeper中存在的详细地址和信息 只存在一个标红框中,因为只有2.7版本有,不需要对2.6版本兼容) ;
黑白名单路由: 黑白名单路由是条件路由的一个子模块,如图 37在控制台配置黑白名单路由;图38在控制台配置完后再zookeeper中生成的路径和条件路由一致,信息修改为url不等于 黑白名单的url。兼容2.6的信息也多了一条。
动态配置 (动态配置 覆盖xml中的配置如图39为xml中配置的timeout ,如图40位 控制中心的timeout配置。 图41位控制台配置完在zookeeper中生成路径和详细信息,为了兼容2.6 也会在41图下面那个图多一条记录 );
图42为 消费者需要监听的目录。 其中包含兼容2.6版本的黑白名单,还有动态配置路径。
图44 55行 56行, 获取RouterFactory 的多个实现类,getActive 是 获取 某一个类上面标有active(key=value).url的值和value 相等就会取出对应的实现类。图45的4个实现类型。53行到55行,调用每一个实现类的 factory.getRouter(url) 返回一个 Router 封装到一个List中。
图45位 四个RouterFactory 工厂, MockRouterFactory ,TagRouterFactory,AppRouterFactory,ServiceRouterFactory.; tagRouterFactory 没有getRouter(url) 方法 所以调用父类CachebleRouterFactory的getRouter(url)方法。图47 33行34行,调用TagRouterFactory类的createRouter(url)的方法,返回一个TagRouter 这个TagRouter 设置默认优先级为 100存在一个map中,key 是url的一个值,然后从新map中获取值返回。
AppRouterFactory中直接调用getRouter(url),图49,调用createRouter(url) 方法,new AppRouter 返回。设置优先级为150
ServiceRouterFactory 没有getRouter(url)方法, 所以调用父类CachebleRouterFactory的getRouter(url)方法。调用ServiceRouterFactory类的createRouter(url)的方法,返回一个ServiceRouter 这个ServiceRouter 设置默认优先级为 140存在一个map中,key 是url的一个值,然后从新map中获取值返回。
386行订阅相关的监听目录,providers,configurator,routers三个目录图81.
389行合并invoker
图28
图29
图30
图30 是否配置了简单的的key, 如果是返回简单的信息不包括监控中心相关无用的信息。减轻zookeeper的压力。
图31
图31为向 zookeeper注册的消费者信息的具体路径信息。
图32
图33
图32
图33
图34
图35
图36
图37
图39
图40
图41
图42
图43
图45
图45位 四个RouterFactory 工厂, MockRouterFactory ,TagRouterFactory,AppRouterFactory,ServiceRouterFactory.
图46
图47
图48
图49
图50
图51
图52
图
图53
图54
图55
图56
图57
图57 AppRouterFactory 和ServiceRouterFactroy 的核心实现 类 为调用ListenableRouter类的构造器方法.图58.
图58
图58 DynamicConfiguration 实现类zookeeperDynamicConfiguration ,如图60;DynamicConfiguration是动态配置,监听config目录下的事件图59 ;
图59
图60
图61 图61 54行为zookeeper的路径,即监听config目录下的路径。60行 连接zookeeper 61行,new的时候开始在这个目录下添加事件。
图62
图62 为属性赋值。
图63
图64
图64 121行监听单个应用或者服务的名字加上.condition-router 后缀,this 就是对应的监听器。
图65
图65把"."换成"/";
图66
图66 获取对应的属性值。图67 获取属性的详细内容。
图67
图68
图68监听事件改变得方法。event包含的详细内容图69;65行到67行 删除事件操作.conditionRoutersList 清空。 70行获取even的文本值,进行解析图72
图69
图70
图71
图71条件路由的类。
图72
图72解析完内容返回一个ConditionRouterRule对象,该对象类为图73 详细内容为图74 获取routerRule 的详细信息。
图73
图74
图74 rawRule 为返回的 详细信息。
图75
图75 把对应的rule规则对应的信息翻译成对应的对象。并赋值到conditionRouters.中。
图76
图76 initWithRouters(routers).,routers详细信息图77. 把这些路由赋值并排序。 排序完后的顺序图78
图77
图78
图79
图79 MockInvoker的优先级为 最小。
图80
图80 构建服务链后,赋值给服务目录的routerChain属性。
图81
监听的三个目录。
图82
图82 对不用的目录进行订阅。154行简单的set方法,155行为为监听的是config下的configurators。 156行监听的serviceConfiguration
图83
图84
图84 获取应用名+.configurators后缀。 监听consumer +.configurators ,
图85
图85 41监听的是 config目录下,configurators的变化图86行。 一旦有变化会 调用process()方法,图87 ,把变化的内容翻译成对象图89
图86
图87
图87 判断是否是删除事件,删除清理configurators属性的值。 62行为转换。 把事件变化的内容 图88 转换成对应的对象,对象的详细信息为90,71行覆盖xml对应的参数,
图88
图89
图90
图91
图92
图92 如果参数变化了。会从新刷新下服务目录的调用者信息。
图93
图94
图94服务订阅
图95 真正的订阅。
图95 真正的订阅。152行根据url (图96)的category属性 的 provides,configurators,routers进行分类. 分类后详细信息为图97 。为每一个路径绑定一个监听器 。163行在zookeeper中创建临时节点。169行进行通知。
图96
图97
图98
图99
图101
图101
图 101 394行获取categoryNotified详细信息图102. 392行 获取 providers,configrators,routers 相关信息并且,依次遍历通知如图105
384行到389行是Url进行过滤。利用isMatch方法进行过滤。
图102
图103
图104
图105
图 105 196行到209行 过滤出 2.6版本的,url内容图106。将内容解析为对应的类。放在configurators中。219行重写和过滤操作图107
图106
图107
图107为重写;
图108
图108 659行,660行为应用重写,662行,663行为服务重写。 把Configurator逐个遍历添加到overrideDirectoryUrl中图109
图109
图110
图110 246行 如果从url中取出的协议是 empty// 开头的协议不是http 那么 就 清空invokers, routeChain也就为空。销毁所有的invokers服务。禁止服务。266行最终newUrlInvokerMap 赋值给urlInvokerMap(可用的Invoker) 282行newInvokers(所有的invokers) 没有过滤前,285通过路由连过滤掉一部分,
图111
图112
图112 把 服务提供者翻译成Invoker ,364行值379行 判断 提供者
图113
图113 434行 根据configurator从写providerUrl 图114
图114
图115
图116
图117
图117 为每个invoker生成一个httpClient
图118
图119
图119 把服务目录包装成 FailoverClusterInvoker. 最终返回给最外部
图120 FailoverClusterInvoker的包装类
图120 FailoverClusterInvoker的包装类 MockClusterWrapper。 消费者调用的是首先拿到这个类再走FailoverClusterInvoker类。
图121
图121 365行到367行解析urls.size()==1的情况(上述情况) 。如果不等于1 证明是http和注册中心地址的的混合 . 378行,如果是注册中心的话添加一个cluster的key,value 为 registryaware, 380行在join时通过url的key cluster 拿到 vlue=registryaware 默认实现类使用RegistryAwareCluster 最终返回RegistryAwareClusterInvoker 图123, 380行,382行 staticDirectory静态目录。
图122行
图123行
图124
图125
图125 静态目录和动态目录,动态目录实现了监听器,静态目录 invokers属性不会变得。 为什么不会变呢,因为在 图121 371行 refprotocol.ref()的时候,在366行已经 做了监听机制了。
图126
图127