摘要:注册中心默认利用了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的实现:
@Overridepublic Exporter export(final Invoker originInvoker) throws RpcException { URL registryUrl = getRegistryUrl(originInvoker); // url to export locally URL 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); // 默以为true if (register) { // 服务注册 register(registryUrl, registeredProviderUrl); } // register stated url on provider model registerStatedUrl(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 export return 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博客,发送订阅截图的私信给作者,将可以获得一份丰富的面试题整理资料,里面收录的面试题多达几百道。 |