Dubbo源码分析之服务注册原理

getRegistry

1. url转化为对应配置的注册中心的具体协议

2. 根据具体协议,从registryFactory中获得指定的注册中心实现

那么这个registryFactory具体是怎么赋值的呢?

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) {

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);

}

// url to registry

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) {

register(registryUrl, registeredProviderUrl);

providerInvokerWrapper.setReg(true);

}private Registry getRegistry(final Invoker originInvoker) {

//url转化为配置的具体协议,比如zookeeper://ip:port. 这样后续获得的注册中心就会是基于

zk的实现

URL registryUrl = getRegistryUrl(originInvoker);

return registryFactory.getRegistry(registryUrl);

}

RegistryProtocol中存在一段这样的代码,很明显这是通过依赖注入来实现的扩展点。

private RegistryFactory registryFactory;

public void setRegistryFactory(RegistryFactory registryFactory) {

this.registryFactory = registryFactory;

}

按照扩展点的加载规则,我们可以先看看/META-INF/dubbo/internal路径下找到RegistryFactory的配

置文件.这个factory有多个扩展点的实现。

dubbo=org.apache.dubbo.registry.dubbo.DubboRegistryFactory

multicast=org.apache.dubbo.registry.multicast.MulticastRegistryFactory

zookeeper=org.apache.dubbo.registry.zookeeper.ZookeeperRegistryFactory

redis=org.apache.dubbo.registry.redis.RedisRegistryFactory

consul=org.apache.dubbo.registry.consul.ConsulRegistryFactory

etcd3=org.apache.dubbo.registry.etcd.EtcdRegistryFactory

接着,找到RegistryFactory的实现, 发现它里面有一个自适应的方法,根据urlprotocol传入的值进行

适配

@SPI("dubbo")

public interface RegistryFactory {

@Adaptive({"protocol"})

Registry getRegistry(URL url);

RegistryFactory$Adaptive

由于在前面的代码中,url中的protocol已经改成了zookeeper,那么这个时候根据zookeeper获得的spi

扩展点应该是ZookeeperRegistryFactoryZookeeperRegistryFactory

这个方法中并没有getRegistry方法,而是在父类AbstractRegistryFactory

从缓存REGISTRIES中,根据key获得对应的Registry

如果不存在,则创建Registry

import org.apache.dubbo.common.extension.ExtensionLoader;

public class RegistryFactory$Adaptive implements

org.apache.dubbo.registry.RegistryFactory {

public org.apache.dubbo.registry.Registry

getRegistry(org.apache.dubbo.common.URL arg0) {

if (arg0 == null) throw new IllegalArgumentException("url == null");

org.apache.dubbo.common.URL url = arg0;

String extName = ( url.getProtocol() == null ? "dubbo" :

url.getProtocol() );

if(extName == null) throw new IllegalStateException("Failed to get

extension (org.apache.dubbo.registry.RegistryFactory) name from url (" +

url.toString() + ") use keys([protocol])");

org.apache.dubbo.registry.RegistryFactory extension =

(org.apache.dubbo.registry.RegistryFactory)ExtensionLoader.getExtensionLoader(or

g.apache.dubbo.registry.RegistryFactory.class).getExtension(extName);

return extension.getRegistry(arg0);

}

}

public Registry getRegistry(URL url) {

url = URLBuilder.from(url)

.setPath(RegistryService.class.getName())

.addParameter(Constants.INTERFACE_KEY,

RegistryService.class.getName())

.removeParameters(Constants.EXPORT_KEY, Constants.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;

}

//创建注册中心

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();

}

}createRegistry

创建一个zookeeperRegistry,把urlzookeepertransporter作为参数传入。

zookeeperTransporter 这个属性也是基于依赖注入来赋值的,具体的流程就不再分析了,这个的值应

该是

CuratorZookeeperTransporter 表示具体使用什么框架来和zk产生连接

ZookeeperRegistry

这个方法中使用了CuratorZookeeperTransport来实现zk的连接

registry.register(registedProviderUrl);

继续往下分析,会调用registry.register去讲dubbo://的协议地址注册到zookeeper

这个方法会调用FailbackRegistry类中的register. 为什么呢?因为ZookeeperRegistry这个类中并没有

register这个方法,但是他的父类FailbackRegistry中存在register方法,而这个类又重写了

AbstractRegistry类中的register方法。所以我们可以直接定位大FailbackRegistry这个类中的register

法中

public Registry createRegistry(URL url) {

return new ZookeeperRegistry(url, zookeeperTransporter);

}

public ZookeeperRegistry(URL url, ZookeeperTransporter zookeeperTransporter) {

super(url);

if (url.isAnyHost()) {

throw new IllegalStateException("registry address == null");

}

//获得group名称

String group = url.getParameter(Constants.GROUP_KEY, DEFAULT_ROOT);

if (!group.startsWith(Constants.PATH_SEPARATOR)) {

group = Constants.PATH_SEPARATOR + group;

}

this.root = group;

//产生一个zookeeper连接

zkClient = zookeeperTransporter.connect(url);

//添加zookeeper状态变化事件

zkClient.addStateListener(state -> {

if (state == StateListener.RECONNECTED) {

try {

recover();

} catch (Exception e) {

logger.error(e.getMessage(), e);

}

}

});

}

 

你可能感兴趣的:(dubbo)