说在前面
前期回顾
sharding-jdbc源码解析 更新完毕
spring源码解析 更新完毕
spring-mvc源码解析 更新完毕
spring-tx源码解析 更新完毕
spring-boot源码解析 更新完毕
rocketmq源码解析 更新完毕
dubbo源码解析 更新中
sharding-sphere源码解析 计划中
netty源码解析 计划中
spring-cloud-alibaba-dubbo源码解析 计划中
github https://github.com/tianheframe
sharding-jdbc源码解析 更新完毕
rocketmq 更新完毕
dubbo源码解析 更新中
seata源码解析 更新中
spring-cloud-tianhe 更新中
mq-tianhe 计划中
rpc-tianhe 计划中
更多源码解析请关注天河聊架构微信公众号
源码解析
https://github.com/tianheframe/dubbo.git dubbo源码解析后的源码和公号文章同步更新。
返回放到这个方法,com.alibaba.dubbo.config.ServiceConfig#doExportUrlsFor1Protocol的这里
Invoker<?> invoker = proxyFactory.getInvoker(ref, (Class) interfaceClass, registryURL.addParameterAndEncoded(Constants.EXPORT_KEY, url.toFullString()));
DelegateProviderMetaDataInvoker wrapperInvoker = new DelegateProviderMetaDataInvoker(invoker, this);
// ProtocolFilterWrapper.export服务注册=》
Exporter<?> exporter = protocol.export(wrapperInvoker);
exporters.add(exporter);
}
} else {
Invoker<?> invoker = proxyFactory.getInvoker(ref, (Class) interfaceClass, url);
DelegateProviderMetaDataInvoker wrapperInvoker = new DelegateProviderMetaDataInvoker(invoker, this);
Exporter<?> exporter = protocol.export(wrapperInvoker);
exporters.add(exporter);
}
}
}
this.urls.add(url);
proxyFactory.getInvoker调用这个方法会返回一个invoker代理对象
Exporter<?> exporter = protocol.export(wrapperInvoker); 服务export返回一个exporter,会进入到这个方法,com.alibaba.dubbo.rpc.protocol.ProtocolFilterWrapper#export
@Override
public <T> Exporter<T> export(Invoker<T> invoker) throws RpcException {
if (Constants.REGISTRY_PROTOCOL.equals(invoker.getUrl().getProtocol())) {
// ProtocolListenerWrapper.export()
return protocol.export(invoker);
}
// com.alibaba.dubbo.rpc.protocol.ProtocolListenerWrapper.export()=》
return protocol.export(buildInvokerChain(invoker, Constants.SERVICE_FILTER_KEY, Constants.PROVIDER));
}
接下来会进入到这个方法,com.alibaba.dubbo.rpc.protocol.ProtocolListenerWrapper#export
@Override
public <T> Exporter<T> export(Invoker<T> invoker) throws RpcException {
if (Constants.REGISTRY_PROTOCOL.equals(invoker.getUrl().getProtocol())) {
// RegistryProtocol.export()
return protocol.export(invoker);
}
// 这里可以实现自己的ExporterListener实现,在服务export、unexport的时候的监听器实现 com.alibaba.dubbo.rpc.protocol.injvm.InjvmProtocol.export()=》
return new ListenerExporterWrapper<T>(protocol.export(invoker),
Collections.unmodifiableList(ExtensionLoader.getExtensionLoader(ExporterListener.class)
.getActivateExtension(invoker.getUrl(), Constants.EXPORTER_LISTENER_KEY)));
}
接下来会进入到这个方法,com.alibaba.dubbo.registry.integration.RegistryProtocol#export
@Override
public <T> Exporter<T> export(final Invoker<T> originInvoker) throws RpcException {
//export invoker 本地服务=》
final ExporterChangeableWrapper<T> exporter = doLocalExport(originInvoker);
// 查询注册的url=》
URL registryUrl = getRegistryUrl(originInvoker);
//registry provider 注册服务提供者=》ZookeeperRegistry
final Registry registry = getRegistry(originInvoker);
// 查询注册的provider url=》
final URL registeredProviderUrl = getRegisteredProviderUrl(originInvoker);
//to judge to delay publish whether or not 判断是否推迟发布,获取register参数是否进行服务注册,开发测试中可以设置为不注册,用服务直连
boolean register = registeredProviderUrl.getParameter("register", true);
// 注册provider=》
ProviderConsumerRegTable.registerProvider(originInvoker, registryUrl, registeredProviderUrl);
if (register) {
// 服务注册=》
register(registryUrl, registeredProviderUrl);
ProviderConsumerRegTable.getProviderWrapper(originInvoker).setReg(true);
}
// Subscribe the override data
// FIXME When the provider subscribes, it will affect the scene : a certain JVM exposes the service and call the same service. Because the subscribed is cached key with the name of the service, it causes the subscription information to cover.
// 当提供者订阅时,它将影响场景:某个JVM公开服务并调用相同的服务。因为订阅是带有服务名称的缓存键,所以它会导致订阅信息覆盖。
final URL overrideSubscribeUrl = getSubscribedOverrideUrl(registeredProviderUrl);
final OverrideListener overrideSubscribeListener = new OverrideListener(overrideSubscribeUrl, originInvoker);
overrideListeners.put(overrideSubscribeUrl, overrideSubscribeListener);
// 服务订阅=》FailbackRegistry.subscribe
registry.subscribe(overrideSubscribeUrl, overrideSubscribeListener);
//Ensure that a new exporter instance is returned every time export 确保每次导出时都返回一个新的导出实例
return new DestroyableExporter<T>(exporter, originInvoker, overrideSubscribeUrl, registeredProviderUrl);
}
接下来会进入到这个方法,com.alibaba.dubbo.registry.integration.RegistryProtocol#doLocalExport 从本地进行服务export
private <T> ExporterChangeableWrapper<T> doLocalExport(final Invoker<T> originInvoker) {
String key = getCacheKey(originInvoker);
ExporterChangeableWrapper<T> exporter = (ExporterChangeableWrapper<T>) bounds.get(key);
if (exporter == null) {
synchronized (bounds) {
exporter = (ExporterChangeableWrapper<T>) bounds.get(key);
if (exporter == null) {
final Invoker<?> invokerDelegete = new InvokerDelegete<T>(originInvoker, getProviderUrl(originInvoker));
// 导出服务=》ListenerExporterWrapper
exporter = new ExporterChangeableWrapper<T>((Exporter<T>) protocol.export(invokerDelegete), originInvoker);
bounds.put(key, exporter);
}
}
}
return exporter;
}
invoker代理对象对的地址是这样的,interface com.alibaba.dubbo.demo.DemoService -> registry://192.168.50.251:2181/com.alibaba.dubbo.registry.RegistryService?application=demo-provider&dubbo=2.0.2&export=dubbo://172.28.83.80:20880/com.alibaba.dubbo.demo.DemoService?anyhost=true&application=demo-provider&bean.name=com.alibaba.dubbo.demo.DemoService&bind.ip=172.28.83.80&bind.port=20880&dubbo=2.0.2&generic=false&interface=com.alibaba.dubbo.demo.DemoService&methods=sayHello&pid=74694&qos.port=22222&side=provider×tamp=1569832059888&pid=74694&qos.port=22222®istry=zookeeper×tamp=1569832059853
这个地址中有服务的详细参数
进入这个方法进行服务注册,com.alibaba.dubbo.registry.support.ProviderConsumerRegTable#registerProvider
public static void registerProvider(Invoker invoker, URL registryUrl, URL providerUrl) {
ProviderInvokerWrapper wrapperInvoker = new ProviderInvokerWrapper(invoker, registryUrl, providerUrl);
// service唯一的名字 group/interface:version
String serviceUniqueName = providerUrl.getServiceKey();
Set<ProviderInvokerWrapper> invokers = providerInvokers.get(serviceUniqueName);
if (invokers == null) {
providerInvokers.putIfAbsent(serviceUniqueName, new ConcurrentHashSet<ProviderInvokerWrapper>());
invokers = providerInvokers.get(serviceUniqueName);
}
invokers.add(wrapperInvoker);
}
进入这个方法服务注册com.alibaba.dubbo.registry.integration.RegistryProtocol#register
public void register(URL registryUrl, URL registedProviderUrl) {
// 查询注册器=》
Registry registry = registryFactory.getRegistry(registryUrl);
// 服务注册=》FailbackRegistry.register()
registry.register(registedProviderUrl);
}
进入这个方法,com.alibaba.dubbo.registry.support.AbstractRegistryFactory#getRegistry获取服务注册器
@Override
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();
// 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();
}
}
进入这个方法,com.alibaba.dubbo.registry.support.AbstractRegistryFactory#createRegistry创建服务注册器,这里解析下zk的服务注册器
@Override
public Registry createRegistry(URL url) {
return new ZookeeperRegistry(url, zookeeperTransporter);
}
进入这个方法,com.alibaba.dubbo.registry.zookeeper.ZookeeperRegistry#ZookeeperRegistry
public ZookeeperRegistry(URL url, ZookeeperTransporter zookeeperTransporter) {
super(url);
if (url.isAnyHost()) {
throw new IllegalStateException("registry address == null");
}
String group = url.getParameter(Constants.GROUP_KEY, DEFAULT_ROOT);
if (!group.startsWith(Constants.PATH_SEPARATOR)) {
group = Constants.PATH_SEPARATOR + group;
}
this.root = group;
// 创建zkclient=》
zkClient = zookeeperTransporter.connect(url);
// 添加监听器
zkClient.addStateListener(new StateListener() {
@Override
public void stateChanged(int state) {
if (state == RECONNECTED) {
try {
// 恢复注册信息=》
recover();
} catch (Exception e) {
logger.error(e.getMessage(), e);
}
}
}
});
}
进入这个方法,com.alibaba.dubbo.remoting.zookeeper.ZookeeperTransporter#connect连接zk,dubbo提供了两种实现,zkClient、curator,这里spi默认加载curator
@SPI("curator")
public interface ZookeeperTransporter {
@Adaptive({Constants.CLIENT_KEY, Constants.TRANSPORTER_KEY})
ZookeeperClient connect(URL url);
}
进入这个方法创建zk client,com.alibaba.dubbo.remoting.zookeeper.curator.CuratorZookeeperClient#CuratorZookeeperClient
public CuratorZookeeperClient(URL url) {
super(url);
try {
CuratorFrameworkFactory.Builder builder = CuratorFrameworkFactory.builder()
.connectString(url.getBackupAddress())
.retryPolicy(new RetryNTimes(1, 1000))
.connectionTimeoutMs(5000);
String authority = url.getAuthority();
if (authority != null && authority.length() > 0) {
builder = builder.authorization("digest", authority.getBytes());
}
client = builder.build();
client.getConnectionStateListenable().addListener(new ConnectionStateListener() {
@Override
public void stateChanged(CuratorFramework client, ConnectionState state) {
if (state == ConnectionState.LOST) {
CuratorZookeeperClient.this.stateChanged(StateListener.DISCONNECTED);
} else if (state == ConnectionState.CONNECTED) {
CuratorZookeeperClient.this.stateChanged(StateListener.CONNECTED);
} else if (state == ConnectionState.RECONNECTED) {
CuratorZookeeperClient.this.stateChanged(StateListener.RECONNECTED);
}
}
});
client.start();
} catch (Exception e) {
throw new IllegalStateException(e.getMessage(), e);
}
}
返回到这个方法com.alibaba.dubbo.registry.zookeeper.ZookeeperRegistry#ZookeeperRegistry这里
zkClient.addStateListener(new StateListener() {
@Override
public void stateChanged(int state) {
if (state == RECONNECTED) {
try {
// 恢复注册信息=》
recover();
} catch (Exception e) {
logger.error(e.getMessage(), e);
}
}
}
});
添加zk重新连接的监听器进行服务注册信息恢复
进入这个方法,com.alibaba.dubbo.registry.support.FailbackRegistry#recover
@Override
protected void recover() throws Exception {
// register 查询注册的url
Set<URL> recoverRegistered = new HashSet<URL>(getRegistered());
if (!recoverRegistered.isEmpty()) {
if (logger.isInfoEnabled()) {
logger.info("Recover register url " + recoverRegistered);
}
for (URL url : recoverRegistered) {
failedRegistered.add(url);
}
}
// subscribe 查询订阅信息
Map<URL, Set<NotifyListener>> recoverSubscribed = new HashMap<URL, Set<NotifyListener>>(getSubscribed());
if (!recoverSubscribed.isEmpty()) {
if (logger.isInfoEnabled()) {
logger.info("Recover subscribe url " + recoverSubscribed.keySet());
}
for (Map.Entry<URL, Set<NotifyListener>> entry : recoverSubscribed.entrySet()) {
URL url = entry.getKey();
for (NotifyListener listener : entry.getValue()) {
addFailedSubscribed(url, listener);
}
}
}
}
下篇继续介绍服务注册信息恢复逻辑
说在最后
本次解析仅代表个人观点,仅供参考。