RegistryProtocol
在dubbo服务发布流程已经分析了发布服务流程还有服务注册流程
export
在RegistryProtocol#export
继续服务注册流程
// 根据invoker中的url获取Registry实例: zookeeperRegistry
// ListenerRegistryWrapper(ZookeeperRegistry) 后面注册服务阐述
final Registry registry = getRegistry(originInvoker);
// 获取要注册的到注册中心的URL: dubbo://ip:port
final URL registeredProviderUrl = getUrlToRegistry(providerUrl, registryUrl);
// decide if we need to delay publish
boolean register = providerUrl.getParameter(REGISTER_KEY, true);
// 是否配置了注册中心,如果是,则需要注册
if (register) {
// 将ProviderURL注册到注册中心
register(registryUrl, registeredProviderUrl);
}
getRegistry
protected Registry getRegistry(final Invoker<?> originInvoker) {
// 把 url 转化为对应配置的注册中心的具体协议 如:zookeeper://ip:port
URL registryUrl = getRegistryUrl(originInvoker);
// 根据具体协议从registryFactory获取指定的注册中心实现 ZookeeperRegistry
return registryFactory.getRegistry(registryUrl);
}
RegistryProtocol#register
public void register(URL registryUrl, URL registeredProviderUrl) {
// registryFactory是一个扩展点RegistryFactory$Adaptive
// 并且这个扩展点有一个包装类 RegistryFactoryWrapper
// 最终获取的的registryFactory是RegistryFactoryWrapper(ZookeeperRegistryFactory)
// 这里获得的registry的是 ListenerRegistryWrapper(ZookeeperRegistry)
Registry registry = registryFactory.getRegistry(registryUrl);
registry.register(registeredProviderUrl);
ProviderModel model = ApplicationModel.getProviderModel(registeredProviderUrl.getServiceKey());
model.addStatedUrl(new ProviderModel.RegisterStatedURL(
registeredProviderUrl,
registryUrl,
true
));
}
RegistryFactory
方法级别自适应扩展点在RegistryProtocol
通过set依赖注入
@SPI("dubbo")
public interface RegistryFactory {
@Adaptive({"protocol"})
Registry getRegistry(URL url);
}
RegistryFactory
扩展点的配置文件META-INF\dubbo\internal\org.apache.dubbo.registry.RegistryFactory
service-discovery-registry=org.apache.dubbo.registry.client.ServiceDiscoveryRegistryFactory
wrapper=org.apache.dubbo.registry.RegistryFactoryWrapper
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
nacos=org.apache.dubbo.registry.nacos.NacosRegistryFactory
sofa=org.apache.dubbo.registry.sofa.SofaRegistryFactory
multiple=org.apache.dubbo.registry.multiple.MultipleRegistryFactory
RegistryFactory$Adaptive
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;
// extName -> zookeeper
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])");
// 返回的RegistryFactory是RegistryFactoryWrapper(ZookeeperRegistryFactory)
org.apache.dubbo.registry.RegistryFactory extension = (org.apache.dubbo.registry.RegistryFactory)ExtensionLoader.getExtensionLoader(org.apache.dubbo.registry.RegistryFactory.class).getExtension(extName);
return extension.getRegistry(arg0);
}
}
RegistryFactoryWrapper
可以看到RegistryFactory的扩展点配置文件中有wrapper=org.apache.dubbo.registry.RegistryFactoryWrapper
所有RegistryFactory$Adaptive#getRegistry
方法中获取的RegistryFactory
是用RegistryFactoryWrapper
增强的ZookeeperRegistryFactory
public class RegistryFactoryWrapper implements RegistryFactory {
private RegistryFactory registryFactory;
public RegistryFactoryWrapper(RegistryFactory registryFactory) {
this.registryFactory = registryFactory;
}
@Override
public Registry getRegistry(URL url) {
return new ListenerRegistryWrapper(registryFactory.getRegistry(url),
Collections.unmodifiableList(ExtensionLoader.getExtensionLoader(RegistryServiceListener.class)
.getActivateExtension(url, "registry.listeners")));
}
}
ZookeeperRegistryFactory
getRegistry
ZookeeperRegistryFactory
中没有看到getRegistry
所有调用其父类AbstractRegistryFactory
的getRegistry方法
public class ZookeeperRegistryFactory extends AbstractRegistryFactory {
private ZookeeperTransporter zookeeperTransporter;
/**
* Invisible injection of zookeeper client via IOC/SPI
* @param zookeeperTransporter
*/
public void setZookeeperTransporter(ZookeeperTransporter zookeeperTransporter) {
this.zookeeperTransporter = zookeeperTransporter;
}
@Override
public Registry createRegistry(URL url) {
return new ZookeeperRegistry(url, zookeeperTransporter);
}
}
AbstractRegistryFactory.getRegistry
public Registry getRegistry(URL url) {
if (destroyed.get()) {
LOGGER.warn("All registry instances have been destroyed, failed to fetch any instance. " +
"Usually, this means no need to try to do unnecessary redundant resource clearance, all registries has been taken care of.");
return DEFAULT_NOP_REGISTRY;
}
// 获取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 {
// 从缓存中获取Register
Registry registry = REGISTRIES.get(key);
if (registry != null) {
return registry;
}
//create registry by spi/ioc
// 创建registry
registry = createRegistry(url); // 这是一个模板方法,有子类实现如ZookeeperRegistryFactory.createRegistry
if (registry == null) {
throw new IllegalStateException("Can not create registry " + url);
}
REGISTRIES.put(key, registry);
return registry;
} finally {
// Release the lock
LOCK.unlock();
}
}
createRegistry
ZookeeperRegistryFactory#createRegistry
@Override
public Registry createRegistry(URL url) {
return new ZookeeperRegistry(url, zookeeperTransporter);
}
通过上面的方法最终得到的registry是ListenerRegistryWrapper(ZookeeperRegistry)
ZookeeperRegistry
ZookeeperRegistry构造函数
这个方法中使用了 CuratorZookeeperTransport 来实现 zk 的连接
public class ZookeeperRegistry extends FailbackRegistry {
private final static Logger logger = LoggerFactory.getLogger(ZookeeperRegistry.class);
private final static String DEFAULT_ROOT = "dubbo";
private final String root;
private final Set<String> anyServices = new ConcurrentHashSet<>();
private final ConcurrentMap<URL, ConcurrentMap<NotifyListener, ChildListener>> zkListeners = new ConcurrentHashMap<>();
private final ZookeeperClient zkClient;
public ZookeeperRegistry(URL url, ZookeeperTransporter zookeeperTransporter) {
super(url);
if (url.isAnyHost()) {
throw new IllegalStateException("registry address == null");
}
// 获得group名称
String group = url.getParameter(GROUP_KEY, DEFAULT_ROOT);
if (!group.startsWith(PATH_SEPARATOR)) {
group = PATH_SEPARATOR + group;
}
this.root = group;
// ZookeeperTransporter是一个扩展点 基于方法适配 默认使用curator实现
// 产生一个zookeeper连接
zkClient = zookeeperTransporter.connect(url);
// 添加zookeeper状态变化事件
zkClient.addStateListener((state) -> {
if (state == StateListener.RECONNECTED) {
logger.warn("Trying to fetch the latest urls, in case there're provider changes during connection loss.\n" +
" Since ephemeral ZNode will not get deleted for a connection lose, " +
"there's no need to re-register url of this instance.");
ZookeeperRegistry.this.fetchLatestAddresses();
} else if (state == StateListener.NEW_SESSION_CREATED) {
logger.warn("Trying to re-register urls and re-subscribe listeners of this instance to registry...");
try {
ZookeeperRegistry.this.recover();
} catch (Exception e) {
logger.error(e.getMessage(), e);
}
} else if (state == StateListener.SESSION_LOST) {
logger.warn("Url of this instance will be deleted from registry soon. " +
"Dubbo client will try to re-register once a new session is created.");
} else if (state == StateListener.SUSPENDED) {
} else if (state == StateListener.CONNECTED) {
}
});
}
registry.register(registedProviderUrl)
继续往下分析,会调用 registry.register 去将 dubbo://的协议地址注册到 zookeeper 上
ZookeeperRegistry 这个类中并没有 register 这个方法,但是他的父类 FailbackRegistry 中存在 register 方法,而这个类又重写了 AbstractRegistry 类中的 register 方法。所以我们可以直接定位到 FailbackRegistry 这个类中的 register 方法中
FailbackRegistry.register
public void register(URL url) {
if (!acceptable(url)) {
logger.info("URL " + url + " will not be registered to Registry. Registry " + url + " does not accept service of this protocol type.");
return;
}
super.register(url);
removeFailedRegistered(url);
removeFailedUnregistered(url);
try {
// 调用子类实现真正的服务注册,把 url 注册到 zk 上
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);
}
// 将失败的注册请求记录到失败列表,定时重试
addFailedRegistered(url);
}
}
ZookeeperRegistry.doRegister
最终调用 curator 的客户端把服务地址注册到 zk
public void doRegister(URL url) {
try {
// 这个zkClient 是CuratorZookeeperClient 也是基于扩展点机制实现的
zkClient.create(toUrlPath(url), url.getParameter(DYNAMIC_KEY, true));
} catch (Throwable e) {
throw new RpcException("Failed to register " + url + " to zookeeper " + getUrl() + ", cause: " + e.getMessage(), e);
}
}