服务的注册、消费
在使用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中, protocol 、 refprotocol 的值都是 ExtensionLoader.getExtensionLoader(Protocol.class).getAdaptiveExtension() 。 即Protocol$Adaptive这个动态生成类。在这个动态类中,会取得url.getProtocol(),并获得对应name的Extension。即RegistryProtocol。
RegistryProtocol为Protocol接口的实现类,接口的两个重要方法为**export(Invoker
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的代码:
@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