Dubbo之服务注册
在上一篇文章Dubbo之服务暴露分析中介绍了当远程暴露时,如果有注册中心,需要在服务暴露后再将服务注册到注册中心。该篇将介绍该功能的有关步骤。
注册的起点
在RegistryProtocol.export()
方法包含了服务导出,注册,以及数据订阅等逻辑。其中服务注册先调用RegistryProtocol.register()
方法。
public void register(URL registryUrl, URL registeredProviderUrl) { // 获取 Registry Registry registry = registryFactory.getRegistry(registryUrl); // 注册服务 registry.register(registeredProviderUrl); }
可以看出,服务注册主要包括两部分,获取注册中心实例和向注册中心注册服务。
获取注册中心实例
(1)调用registryFactory.getRegistry(registryUrl)
方法,它会先访问缓存,缓存中不存在则调用createRegistry(URL)
方法创建Registry,然后写入缓存。这里的createRegistry是一个模版方法,有具体的子类实现。这里假设使用zookeeper作为注册中心,则调用ZookeeperRegistryFactory的createRegistry()方法。
public Registry createRegistry(URL url) { // 创建 ZookeeperRegistry return new ZookeeperRegistry(url, zookeeperTransporter); }
public ZookeeperRegistry(URL url, ZookeeperTransporter zookeeperTransporter) { super(url); if (url.isAnyHost()) { throw new IllegalStateException("registry address == null"); } // 获取组名,默认为 dubbo String group = url.getParameter(Constants.GROUP_KEY, DEFAULT_ROOT); if (!group.startsWith(Constants.PATH_SEPARATOR)) { // group = "/" + group group = Constants.PATH_SEPARATOR + group; } this.root = group; // 创建 Zookeeper 客户端,默认为 CuratorZookeeperTransporter zkClient = zookeeperTransporter.connect(url); // 添加状态监听器 zkClient.addStateListener(new StateListener() { @Override public void stateChanged(int state) { if (state == RECONNECTED) { try { recover(); } catch (Exception e) { logger.error(e.getMessage(), e); } } } }); }
(2) 在ZookeeperRegistry
构造方法中调用connect(url)
方法,默认是CuratorZookeeperClient
, 获得一个ZkClient客户端,之后添加状态监听器。
向注册中心注册服务
假设存在一个服务com.alibaba.dubbo.demo.DemoService, 那么 这个服务对应的配置信息(存储在 URL 中)最终被注册到了 /dubbo/com.alibaba.dubbo.demo.DemoService/providers/ 节点下。
(1) 调用FailbackRegistry.register()
方法,之后调用里面的doRegister
方法,它是一个模版方法,在ZookeeperRegistry
中实现。
protected void doRegister(URL url) { try { // 通过 Zookeeper 客户端创建节点,节点路径由 toUrlPath 方法生成,路径格式如下: // /${group}/${serviceInterface}/providers/${url} zkClient.create(toUrlPath(url), url.getParameter(Constants.DYNAMIC_KEY, true)); } catch (Throwable e) { throw new RpcException("Failed to register..."); } }
(2) 调用create()
方法。通过递归创建当前节点的上一级路径,然后再根据ephemeral的值决定是创建临时还是持久节点。分别调用createEphemeral
和createPersistent
方法。