执行入口,RegistryProtocol#refer ----> doRefer方法。
1.构建RegistryDirectory对象,基于注册中心动态发现服务提供者
2.为RegistryDirectory设置注册中心、协议。
3.获取服务消费者的配置属性,构建消费者url
4.为消息消费者添加category=providers,configurators,routers属性后,然后向注册中心订阅该URL,关注该服务下的providers,configurators,routers发生变化时通知RegistryDirectory,以便及时发现服务提供者、配置、路由规则的变化。
5.获取集群invoker,然后缓存consumer,provider的对应关系
6.根据category=providers、configurators、routers,分别在该服务名下的providers目录、configurators目录、routers目录建立事件监听,监听该目录下节点的创建、更新、删除事件,然后一旦事件触发,将回调RegistryDirectory#void notify(List< URL> urls)。
7.RegistryDirectory#notify
首先该方法是在注册中心providers、configurators、routers目录下的节点发生变化后,通知RegistryDirectory,已便更新最新信息,实现”动态“发现机制。
8. 从url中,获取协议protocol,category,然后匹配添加到routerUrls, configuratorUrls,invokerUrls
9.如果invokerUrls不为空并且长度为1,并且协议为empty,表示该服务的所有服务提供者都下线了。需要销毁当前所有的服务提供者Invoker。
10.遍历所有的invokerUrls,协议为空就跳过
总结一下服务注册与发现机制:
基于注册 中心的事件通知(订阅与发布),一切支持事件订阅与发布的框架都可以作为Dubbo注册中心的选型。
服务提供者在暴露服务时,会向注册中心注册自己,具体就是在${service interface}/providers目录下添加 一个节点(临时),服务提供者需要与注册中心保持长连接,一旦连接断掉(重试连接)会话信息失效后,注册中心会认为该服务提供者不可用(提供者节点会被删除)。
消费者在启动时,首先也会向注册中心注册自己,具体在${interface interface}/consumers目录下创建一个节点。
消费者订阅${service interface}/ [ providers、configurators、routers ]三个目录,这些目录下的节点删除、新增事件都胡通知消费者,根据通知,重构服务调用器(Invoker)。
当在dubbo-admin(管理后台)中创建一条override规则后,会首先存储在注册中心(zookeeper的指定目录下${service}/configurators目录下,此时基于注册中心的事件机制,会通知相关监听者(服务消费者),服务消费者收到最新的配置时,会根据最新的配置重新构建Invoker对象,然后销毁原先的Invoker对象。
以上就是Dubbo服务注册与动态发现机制的原理与实现细节。
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
dubbo 支持的注册中心如上图
流程说明:
-
服务提供者启动时: 向
/dubbo/com.foo.BarService/providers
目录下写入自己的 URL 地址 -
服务消费者启动时: 订阅
/dubbo/com.foo.BarService/providers
目录下的提供者 URL 地址。并向/dubbo/com.foo.BarService/consumers
目录下写入自己的 URL 地址 -
监控中心启动时: 订阅
/dubbo/com.foo.BarService
目录下的所有提供者和消费者 URL 地址
zookeeper创建对应的节点
doSubscribe 订阅方法
处理所有 Service 层的发起订阅,例如监控中心的订阅
获得 url 对应的监听器集合
获得 ChildListener 对象
创建 Service 节点。该节点为持久节点。
处理指定 Service 层的发起订阅,例如服务消费者的订阅
向 Zookeeper ,PATH 节点,发起订阅
首次全量数据获取完成时,调用 NotifyListener#notify(url, listener, currentChilds)
方法,回调 NotifyListener 的逻辑。这样,服务消费者可创建所有的 Invoker 对象,用于调用服务提供者们。
lookup
查询符合条件的已注册数据,与订阅的推模式相对应,这里为拉模式,只返回一次结果。
- 调用
RegistryService#register(url)
方法,向注册中心注册自己(服务消费者)。 - 调用
Directory#subscribe(url)
方法,向注册中心订阅服务提供者 + 路由规则 + 配置规则。- 在该方法中,会循环获得到的服务体用这列表,调用
Protocol#refer(type, url)
方法,创建每个调用服务的 Invoker 对象。
- 在该方法中,会循环获得到的服务体用这列表,调用