前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >dubbo学习(五)服务发布-zookeeper的连接

dubbo学习(五)服务发布-zookeeper的连接

作者头像
虞大大
发布2020-10-28 17:13:43
6950
发布2020-10-28 17:13:43
举报
文章被收录于专栏:码云大作战码云大作战

一、服务端provider发布流程回顾

根据dubbo启动日志,provider的发布动作为以下几个步骤:

(1)暴露本地服务

Export dubbo service com.ywl.dubbo.TestApi to local registry, dubbo version: 2.0.0, current host: 127.0.0.1。

(2)暴露远程服务

Export dubbo service com.ywl.dubbo.TestApi to url dubbo://192.168.24.69:20880/com.ywl.dubbo.TestApi...后面省略。

(3)启动netty

Start NettyClient yuwenlei.local/192.168.24.69 connect to the server /192.168.1.100:20041, dubbo version: 2.0.0, current host: 192.168.24.69。

(4)打开zk

Opening socket connection to server dailyzk.webuy.ai/192.168.49.11:2181。

(5)注册provider服务到zk

Register dubbo service com.ywl.dubbo.TestApi url dubbo://192.168.24.69:20880/com.ywl.dubbo.TestApi? ...中间省略。

to registry registry://dailyzk.webuy.ai:7005/org.apache.dubbo.registry.RegistryService? ...后面省略。

(6)监听zk(订阅与通知)

Subscribe: provider://192.168.24.69:20880/com.ywl.dubbo.TestApi?...后面省略。

Notify urls for subscribe url provider://192.168.24.69:20880/com.ywl.dubbo.TestApi?...后面省略。

· 服务发布的目的

解析dubbo-provider.xml中的接口。将服务提供者向注册中心注册服务,以便服务消费者从注册中心查询并调用服务。

代码语言:javascript
复制
<dubbo:service interface="com.ywl.dubbo.TestApi" ref="testApi" retries="0"
               cluster="failfast" timeout="3000"/>

二、zookeeper的连接

上篇中讲到了本地服务的暴露和远程服务的暴露(服务暴露和netty服务的暴露)。这篇主要分析的是远程服务暴露中的zookeeper连接的原理。

重新回到远程服务暴露的源码中,即org.apache.dubbo.registry.integration.RegistryProtocol#export

代码语言:javascript
复制
public <T> Exporter<T> export(final Invoker<T> originInvoker) throws RpcException {
    //暴露服务
    final ExporterChangeableWrapper<T> exporter = doLocalExport(originInvoker);
    URL registryUrl = getRegistryUrl(originInvoker);
    //获取注册中心信息 - 在这一步会进行zookeeper的连接
    final Registry registry = getRegistry(originInvoker);
    //...
代码语言:javascript
复制
}

从上述源码中可以看到,暴露远程服务后,就需要获取注册中心信息,同时进行zookeeper的连接。

· 获取注册中心对象

代码语言:javascript
复制
private Registry getRegistry(final Invoker<?> originInvoker) {
    URL registryUrl = getRegistryUrl(originInvoker);
    return registryFactory.getRegistry(registryUrl);
}

通过工厂模式创建注册对象,最终进入到AbstractRegistryFactory中进行注册中心对象的初始化。

代码语言:javascript
复制
public Registry getRegistry(URL url) {
    url = url.setPath(RegistryService.class.getName())
            .addParameter(Constants.INTERFACE_KEY, RegistryService.class.getName())
.removeParameters(Constants.EXPORT_KEY, Constants.REFER_KEY);
    //key - zookeeper://zk的ip+端口/默认RegistryService路径名/group名/version号    String key = url.toServiceString();
    LOCK.lock();
    try {
        Registry registry = REGISTRIES.get(key);
        if (registry != null) {
            return registry;
        }        //缓存不存在 则创建注册信息
        registry = createRegistry(url);
        if (registry == null) {
            throw new IllegalStateException("Can not create registry " + url);
        }
        REGISTRIES.put(key, registry);
        return registry;
    } finally {
        LOCK.unlock();
    }
}

上述源码比较简单,先根据url信息封装key-zookeeper前缀+zk的ip+zk的端口+RegistryService路径名+配置的dubbo的group名+配置的dubbo的版本号组合为key。先根据key查询缓存,缓存存在则直接返回,缓存不存在则进行初始化,放入到缓存中。

· 创建注册中心

代码语言:javascript
复制
public Registry createRegistry(URL url) {
    return new ZookeeperRegistry(url, zookeeperTransporter);
}//步骤一 加载本地配置到内存中
代码语言:javascript
复制
public AbstractRegistry(URL url) {
    setUrl(url);
    syncSaveFile = url.getParameter(Constants.REGISTRY_FILESAVE_SYNC_KEY, false);
    String filename = url.getParameter(Constants.FILE_KEY, System.getProperty("user.home") + "/.dubbo/dubbo-registry-" + url.getParameter(Constants.APPLICATION_KEY) + "-" + url.getAddress() + ".cache");
    //获取配置信息本地缓存的文件    File file = null;
    if (ConfigUtils.isNotEmpty(filename)) {
        file = new File(filename);
        if (!file.exists() && file.getParentFile() != null && !file.getParentFile().exists()) {
            if (!file.getParentFile().mkdirs()) {
                throw new IllegalArgumentException("Invalid registry store file " + file + ", cause: Failed to create directory " + file.getParentFile() + "!");
            }
        }
    }    this.file = file;    //如果存在本地缓存文件则从文件中加载属性,文件中主要存放的是每个接口的注册中心的地址    loadProperties();
    //通知触发所有监听器    notify(url.getBackupUrls());
}
步骤二:检测注册中心,如果失败了进行重连public FailbackRegistry(URL url) {
    //...
    this.retryFuture = retryExecutor.scheduleWithFixedDelay(new Runnable() {
        @Override
        public void run() {
            try {                //建立线程池检测注册中心,如果失败了进行重连                retry();
            } catch (Throwable t) {
                logger.error("Unexpected error occur at failed retry, cause: " + t.getMessage(), t);
            }
        }
    }, retryPeriod, retryPeriod, TimeUnit.MILLISECONDS);
}步骤三:zookeeper连接
public ZookeeperRegistry(URL url, ZookeeperTransporter zookeeperTransporter) {
    //...    //初始化zookeeper,连接zookeeper    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);
                }
            }
        }
    });
}

创建注册中心的步骤也比较简单,最主要的目的为初始化zookeeper并连接zookeeper,并且存在订阅监听,如果连接断开则进行重连。

下一篇会分析下dubbo是如何订阅zookeeper信息的。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-10-10,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 码云大作战 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
微服务引擎 TSE
微服务引擎(Tencent Cloud Service Engine)提供开箱即用的云上全场景微服务解决方案。支持开源增强的云原生注册配置中心(Zookeeper、Nacos 和 Apollo),北极星网格(腾讯自研并开源的 PolarisMesh)、云原生 API 网关(Kong)以及微服务应用托管的弹性微服务平台。微服务引擎完全兼容开源版本的使用方式,在功能、可用性和可运维性等多个方面进行增强。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档