Dubbo源码学习(四)

注册中心(一)---RegistryFactory

Posted by 独顽且鄙 on September 8, 2017

服务的注册、消费

在使用dubbo的过程中,注册中心起到了不可或缺的作用。服务的治理、发现等都需要依赖于注册中心。Dubbo提供了多种注册中心的实现,例如:Zookeeper、Redis等等。 在提供者注册服务、消费者消费服务时都需要通过注册中心来实现。

ServiceConfig

private void doExportUrlsFor1Protocol(ProtocolConfig protocolConfig, List<URL> registryURLs) {
    /* .......省略.......... */
    Exporter<?> exporter = protocol.export(invoker);
    /* .......省略.......... */
}

ReferenceConfig

private T createProxy(Map<String, String> map) {
    /* .......省略.......... */
    refprotocol.refer(interfaceClass, url)
    /* .......省略.......... */
}

在ServiceConfig、ReferenceConfig两个API中, protocolrefprotocol 的值都是 ExtensionLoader.getExtensionLoader(Protocol.class).getAdaptiveExtension() 。 即Protocol$Adaptive这个动态生成类。在这个动态类中,会取得url.getProtocol(),并获得对应name的Extension。即RegistryProtocol

RegistryProtocol为Protocol接口的实现类,接口的两个重要方法为**export(Invoker invoker)**,**refer(Class type, URL url)**,分别为暴露服务、引用服务。 在RegistryProtocol的这两个方法中,我们先只关注有关注册中心的逻辑。

public class RegistryProtocol implements Protocol {
    private RegistryFactory registryFactory;
    
    public <T> Exporter<T> export(final Invoker<T> originInvoker) throws RpcException {
        ...
        //registry provider
        final Registry registry = getRegistry(originInvoker);
        final URL registedProviderUrl = getRegistedProviderUrl(originInvoker);
        registry.register(registedProviderUrl);     //具体注册中心进行注册url
        ...
    }
    
    private Registry getRegistry(final Invoker<?>>originInvoker){
        URL registryUrl = originInvoker.getUrl();
        if (Constants.REGISTRY_PROTOCOL.equals(registryUrl.getProtocol())) {
            String protocol = registryUrl.getParameter(Constants.REGISTRY_KEY, Constants.DEFAULT_DIRECTORY);
            registryUrl = registryUrl.setProtocol(protocol).removeParameter(Constants.REGISTRY_KEY);
        }
        return registryFactory.getRegistry(registryUrl);
    }
}

从RegistryProtocol的代码中可以看出,通过注入的RegistryFactory获取具体Registry对象,通过Registry来完成注册中心的具体的逻辑。

RegistryFactory

RegistryFactory的作用是用来获取Registry对象,RegistryFactory的体系如下图:

RegistryFactory

先看下RegistryFactory的代码:

@SPI("dubbo")
public interface RegistryFactory {
    @Adaptive({"protocol"})
    Registry getRegistry(URL url);
}

RegistryFactory接口只有一个方法,即获取Registry对象,此方法为@Adaptive方法,会在url里取得protocol的值并获取对应的扩展,生成的动态扩展代码应如下:

public class RegistryFactory$Adpative implements RegistryFactory {

    public Registry getRegistry(URL arg0) {
        if (arg0 == null){
            throw new IllegalArgumentException("url == null");
        }

        URL url = arg0;
        String extName = (url.getProtocol() == null ? "dubbo" : url.getProtocol());
        if (extName == null) {
            throw new IllegalStateException("Fail to get extension(com.alibaba.dubbo.registry.RegistryFactory) name from url(" + url.toString() + ") use keys([protocol])");
        }

        RegistryFactory extension = ExtensionLoader.getExtensionLoader(RegistryFactory.class).getExtension(extName);
        return extension.getRegistry(arg0);
    }
}

AbstractRegistryFactory

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);
	String key = url.toServiceString();
    // 锁定注册中心获取过程,保证注册中心单一实例(锁住create的过程,否则可能重复create)
    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();
    }

protected abstract Registry createRegistry(URL url);

AbstractRegistryFactory是个抽象类,实现了RegistryFactory接口。在getRegistry方法中,先去缓存中查找,如果没有,则调用抽象方法createRegistry(URL url)进行创建,具体逻辑由其子类来实现。

ZookeeperRegistryFactroy

public class ZookeeperRegistryFactory extends AbstractRegistryFactory {
	
	private ZookeeperTransporter zookeeperTransporter;

    public void setZookeeperTransporter(ZookeeperTransporter zookeeperTransporter) {
		this.zookeeperTransporter = zookeeperTransporter;
	}

	public Registry createRegistry(URL url) {
        return new ZookeeperRegistry(url, zookeeperTransporter);
    }

}

ZookeeperRegistryFactroy直接new了一个ZookeeperRegistry对象。 参数中有个ZookeeperTransporter对象,dubbo中实现了两套ZookeeperTransporter实现类,分别基于两种主流的zookeeper客户端,一套是基于zkclient的,一套是基于Curator。

MulticastRegistryFactory

<pre class=”prettyprint> public class MulticastRegistryFactory extends AbstractRegistryFactory {

public Registry createRegistry(URL url) {
    return new MulticastRegistry(url);
}

} </pre>

MulticastRegistryFactory也是直接new了一个MulticastRegistry对象。

DubboRegistryFactory

TODO