Gemini技术窝 发表于 2021-9-29 00:02:21

Dubbo源码深度剖析:注册中央的使用

摘要:注册中心默认利用了Zookeeper,服务提供者怎样注册到 Zookeeper,为什么要作为暂时节点注册到Zookeeper目录?我们带着疑问来阅读文章。


对接注册中心的RegistryProtocol

假如有注册中心时,ServiceConfig剖析出的URL格式就类似:registry://registry-host/org.apache.dubbo.registry.RegistryService?export=URL.encode(“dubbo://service-host/com.foo.FooService?version=1.0.0”),这时候Protocol的按次序执行ProtocolFilterWrapper、ProtocolListenerWrapper,然后ProtocolListenerWrapper就会调用到 RegistryProtocol。
假如没有注册中心时,也是会先执行2个Wrapper,然后才会是DubboProtocol。但是RegistryProtocol最终也是会调用到DubboProtocol进行服务暴露的。
那么这里我们就来看看RegistryProtocol的实现:
@OverridepublicExporter export(final Invoker originInvoker) throws RpcException {URL registryUrl = getRegistryUrl(originInvoker);// url to export locallyURL providerUrl = getProviderUrl(originInvoker);final URL overrideSubscribeUrl = getSubscribedOverrideUrl(providerUrl);final OverrideListener overrideSubscribeListener = new OverrideListener(overrideSubscribeUrl, originInvoker);overrideListeners.put(overrideSubscribeUrl, overrideSubscribeListener);providerUrl = overrideUrlWithConfig(providerUrl, overrideSubscribeListener);//export invoker// 紧张代码:提供者导出服务final ExporterChangeableWrapper exporter = doLocalExport(originInvoker, providerUrl);// url to registry// 获取注册中心final Registry registry = getRegistry(originInvoker);final URL registeredProviderUrl = getUrlToRegistry(providerUrl, registryUrl);// decide if we need to delay publish// 决定是否必要耽误注册boolean register = providerUrl.getParameter(REGISTER_KEY, true);// 默以为trueif (register) {    // 服务注册    register(registryUrl, registeredProviderUrl);}// register stated url on provider modelregisterStatedUrl(registryUrl, registeredProviderUrl, register);exporter.setRegisterUrl(registeredProviderUrl);exporter.setSubscribeUrl(overrideSubscribeUrl);// Deprecated! Subscribe to override rules in 2.6.x or before.registry.subscribe(overrideSubscribeUrl, overrideSubscribeListener);notifyExport(exporter);//Ensure that a new exporter instance is returned every time exportreturn new DestroyableExporter(exporter);}接下来重点跟进register方法,这里就是发起注册的地方。
怎样向Zookeeper注册

Registry接口的默认实现类是ZookeeperRegistry,而ZookeeperRegistry继承于FailbackRegistry,这里我们就看看FailbackRegistry的register方法:
public class ZookeeperRegistry extends FailbackRegistry {    @Override    public void doRegister(URL url) {      try {            // 将服务注册到zk            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);      }    }   private String toCategoryPath(URL url) {      // 服务名+/providers      return toServicePath(url) + PATH_SEPARATOR + url.getParameter(CATEGORY_KEY, DEFAULT_CATEGORY);    }   // 在目录/dubbo/com.foo.BarService/providers写入自己的url地点    private String toUrlPath(URL url) {      return toCategoryPath(url) + PATH_SEPARATOR + URL.encode(url.toFullString());    }看到这里我们就可以知道了,服务提供者向注册中心发起注册的过程,其实就是在指定的zk目录下,写入自己的url,其实最紧张的就是记载了自己的ip+port,背面消费者就可以从该目录下拉取提供者机器列表,然后进行负载均衡地调用。
必要注意的一点是,这里写入zk目录下的节点是暂时节点,暂时节点在客户端连接断开的时候会被自动删除,此时也就是Dubbo节点下线了,然后因为消费者有监听该zk目录的变革,假如zk暂时节点被删除后,消费者是会接收到这个事件的,然后会更新本地的provider的节点列表。
简单总结

看到这里,我们就基本了解了服务提供者的流程了,其实最紧张的就是做了2件事:

[*]在本机启动netty server,监听指定端口,后续消费者将作为netty client连接并发送请求。
[*]向ZK注册中心发起服务注册,并将服务地点写入zk的目录。


更多详细的内容请订阅CSDN专栏:Dubbo源码深度剖析_Gemini的博客-CSDN博客
现在订阅专栏 Dubbo源码深度剖析_Gemini的博客-CSDN博客,发送订阅截图的私信给作者,将可以获得一份丰富的面试题整理资料,里面收录的面试题多达几百道。
页: [1]
查看完整版本: Dubbo源码深度剖析:注册中央的使用