dubbo核心之服务注册(三)

一、服务注册过程

  1. 上一章分析到ServiceBean → ServiceConfig → RegistryProtocol,继续看它的export方法
    1、RegistryProtocol的export方法
    //实现服务的注册和发布
    @Override
    public <T> Exporter<T> export(final Invoker<T> originInvoker) throws RpcException {
        // registryUrl -> zookeeper://ip:port
        URL registryUrl = getRegistryUrl(originInvoker);
        // providerUrl -> dubbo:// ip:port
        URL providerUrl = getProviderUrl(originInvoker);
    
    	// 省略。。。
    
        //TODO 把dubbo:// url注册到zk上
        
        2.
        final Registry registry = getRegistry(originInvoker);
        final URL registeredProviderUrl = getRegisteredProviderUrl(providerUrl, registryUrl);
        ProviderInvokerWrapper<T> providerInvokerWrapper = ProviderConsumerRegTable.registerProvider(originInvoker,
                registryUrl, registeredProviderUrl);
        //to judge if we need to delay publish
        boolean register = registeredProviderUrl.getParameter("register", true);
        if (register) {
        	//7.
            register(registryUrl, registeredProviderUrl);
            providerInvokerWrapper.setReg(true);
        }
    
        // Deprecated! Subscribe to override rules in 2.6.x or before.
        registry.subscribe(overrideSubscribeUrl, overrideSubscribeListener);
    
        exporter.setRegisterUrl(registeredProviderUrl);
        exporter.setSubscribeUrl(overrideSubscribeUrl);
        //Ensure that a new exporter instance is returned every time export
        return new DestroyableExporter<>(exporter);
    }
    
    2. 
    private Registry getRegistry(final Invoker<?> originInvoker) {
    	3.
        URL registryUrl = getRegistryUrl(originInvoker);
        4.
        return registryFactory.getRegistry(registryUrl);
    }
    
    
    3.获取注册中心地址
    private URL getRegistryUrl(Invoker<?> originInvoker) {
        URL registryUrl = originInvoker.getUrl();
        if (REGISTRY_PROTOCOL.equals(registryUrl.getProtocol())) {
        	//REGISTRY_KEY = registry
            // protocol = zookeeper
            String protocol = registryUrl.getParameter(REGISTRY_KEY, DEFAULT_REGISTRY);
            //替换并移除key
            //registryUrl = zookeeper://
            registryUrl = registryUrl.setProtocol(protocol).removeParameter(REGISTRY_KEY);
        }
        return registryUrl;
    }
    
    
    4. registryFactory.getRegistry(registryUrl); 
    
    registryFactory这个是SPI,set方法自动注入,而且getRegistry方法上带有@Adaptive注解,
    所以动态生成RegistryFactory$Adaptive类,url拿到的protocol是zookeeper,
    所以实际调用的是ZookeeperRegistryFactory,但是ZookeeperRegistryFactory用的是
    父类AbstractRegistryFactory的getRegistry方法,如下
    
    @Override
    public Registry getRegistry(URL url) {
        url = URLBuilder.from(url)
                .setPath(RegistryService.class.getName())
                .addParameter(INTERFACE_KEY, RegistryService.class.getName())
                .removeParameters(EXPORT_KEY, REFER_KEY)
                .build();
        String key = url.toServiceStringWithoutResolving();
        // Lock the registry access process to ensure a single instance of the registry
        LOCK.lock();
        try {
        	//缓存
            Registry registry = REGISTRIES.get(key);
            if (registry != null) {
                return registry;
            }
            //create registry by spi/ioc
            //5.
            registry = createRegistry(url);
            if (registry == null) {
                throw new IllegalStateException("Can not create registry " + url);
            }
            REGISTRIES.put(key, registry);
            return registry;
        } finally {
            // Release the lock
            LOCK.unlock();
        }
    }
    
    5.  ZookeeperRegistryFactory
    @Override
    public Registry createRegistry(URL url) {
    	//zookeeperTransporter又是SPI,默认用的是CuratorZookeeperTransporter
    	//6.
        return new ZookeeperRegistry(url, zookeeperTransporter);
    }
    
    6. 
     public ZookeeperRegistry(URL url, ZookeeperTransporter zookeeperTransporter) {
        super(url);
        if (url.isAnyHost()) {
            throw new IllegalStateException("registry address == null");
        }
        String group = url.getParameter(GROUP_KEY, DEFAULT_ROOT);
        if (!group.startsWith(PATH_SEPARATOR)) {
            group = PATH_SEPARATOR + group;
        }
        this.root = group;
        //AbstractZookeeperTransporter → CuratorZookeeperTransporter
        zkClient = zookeeperTransporter.connect(url);
        zkClient.addStateListener(state -> {
            if (state == StateListener.RECONNECTED) {
                try {
                    recover();
                } catch (Exception e) {
                    logger.error(e.getMessage(), e);
                }
            }
        });
    }
    
    7.  RegistryProtocol
    public void register(URL registryUrl, URL registeredProviderUrl) {
    	//ZookeeperRegistry
        Registry registry = registryFactory.getRegistry(registryUrl);
        //8.
        registry.register(registeredProviderUrl);
    }
    
    
    8. 在ZookeeperRegistry父类FailbackRegistry中
    @Override
    public void register(URL url) {
        super.register(url);
        removeFailedRegistered(url);
        removeFailedUnregistered(url);
        try {
            //注册临时节点
            doRegister(url);
        } catch (Exception e) {
        	//失败重试
            Throwable t = e;
    
            // If the startup detection is opened, the Exception is thrown directly.
            boolean check = getUrl().getParameter(Constants.CHECK_KEY, true)
                    && url.getParameter(Constants.CHECK_KEY, true)
                    && !CONSUMER_PROTOCOL.equals(url.getProtocol());
            boolean skipFailback = t instanceof SkipFailbackWrapperException;
            if (check || skipFailback) {
                if (skipFailback) {
                    t = t.getCause();
                }
                throw new IllegalStateException("Failed to register " + url + " to registry " + getUrl().getAddress() + ", cause: " + t.getMessage(), t);
            } else {
                logger.error("Failed to register " + url + ", waiting for retry, cause: " + t.getMessage(), t);
            }
    
            // Record a failed registration request to a failed list, retry regularly
            addFailedRegistered(url);
        }
    }
    
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值