一、SpringIOC初始化时,dubbo服务启动
前面springIOC——refresh()中提到finishRefresh(),会执行所有的监听器,但不具体,也不知道有什么用。现在发现dubbo服务就是在这启动的。
/*org.springframework.context.support.AbstractApplicationContext#refresh*/ public void refresh() throws BeansException, IllegalStateException { ... //这里注册了一个Bean后置处理器 //beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this)); //作用是:实现AppliationListener的Bean初始化时加入一个applicationListeners容器 prepareBeanFactory(beanFactory); ... //执行applicationListeners容器中的applicationListener的方法 //applicationListener.onApplicationEvent() finishRefresh(); ... }
DubboBootstrapApplicationListener.onApplicationEvent(event):dubbo服务启动与关闭
/* org.apache.dubbo.config.spring.context.OneTimeExecutionApplicationContextEventListener#onApplicationEvent */ public final void onApplicationEvent(ApplicationEvent event) { if (isOriginalEventSource(event) && event instanceof ApplicationContextEvent) { onApplicationContextEvent((ApplicationContextEvent) event); } } /* org.apache.dubbo.config.spring.context.DubboBootstrapApplicationListener#onApplicationContextEvent */ public void onApplicationContextEvent(ApplicationContextEvent event) { if (event instanceof ContextRefreshedEvent) { //dubbo服务启动 onContextRefreshedEvent((ContextRefreshedEvent) event); } else if (event instanceof ContextClosedEvent) { //dubbo服务关闭 onContextClosedEvent((ContextClosedEvent) event); } } private void onContextRefreshedEvent(ContextRefreshedEvent event) { //构造方法中初始化的this.dubboBootstrap = DubboBootstrap.getInstance(); dubboBootstrap.start(); } private void onContextClosedEvent(ContextClosedEvent event) { dubboBootstrap.stop(); }
二、dubbo服务启动——DubboBootstrap.start();
public DubboBootstrap start() { if (started.compareAndSet(false, true)) { //初始化 initialize(); if (logger.isInfoEnabled()) { logger.info(NAME + " is starting..."); } // 暴露dubbo服务(<dubbo:service />注册到注册表) exportServices(); // Not only provider register if (!isOnlyRegisterProvider() || hasExportedServices()) { // 2. export MetadataService exportMetadataService(); //3. Register the local ServiceInstance if required registerServiceInstance(); } //引用dubbo服务(<dubbo:reference /> 创建代理) referServices(); if (logger.isInfoEnabled()) { logger.info(NAME + " has started."); } } return this; }
1、initialize():初始化
private void initialize() { if (!initialized.compareAndSet(false, true)) { //已初始化直接返回,CAS保证原子性 return; } //扩展点加载机制,SPI的强化版,强在哪里现在还不知道 //实例化META-INF/dubbo/internal/org.apache.dubbo.common.context.FrameworkExt文件中的三个类 //org.apache.dubbo.common.config.Environment : 环境变量组件,在new DubboBootstrap()时,已经实例化,这里拿的是缓存,下面的configManager也是。 //org.apache.dubbo.rpc.model.ServiceRepository : Service仓库初始化了两个类EchoService、GenericService //org.apache.dubbo.config.context.ConfigManager : dubbo所有的配置信息。 // 所有配置的父类AbstractConfig.addIntoConfigManager()被@PostConstruct注解,Bean初始化后会写入configManager ApplicationModel.initFrameworkExts(); //外部配置读取,对应<dubbo:config-center />,一般未设置 startConfigCenter(); //configManager.configCenter为空时, //使用<dubbo:registry />中配置创建ConfigCenter
//<dubbo:registry address="" />默认的zookeeper,根据address连接zookeeper并获取配置信息,(这里只是获取配置信息,并不是注册) useRegistryAsConfigCenterIfNecessary(); //加载生成registryId ProtocolId loadRemoteConfigs(); //验证标签所有属性 //application、Metadata、Provider、Consumer、Monitor、Metrics、Module、Ssl checkGlobalConfigs(); //初始化元数据服务 initMetadataService(); //初始化事件监听器 initEventListener(); if (logger.isInfoEnabled()) { logger.info(NAME + " has been initialized!"); } }
2、exportServices():注册服务
/* org.apache.dubbo.config.bootstrap.DubboBootstrap#exportServices */ private void exportServices() { //遍历所有<dubbo:service />生成的ServiceBean configManager.getServices().forEach(sc -> { // 与ServiceConfig完全兼容 ServiceConfig serviceConfig = (ServiceConfig) sc; serviceConfig.setBootstrap(this); if (exportAsync) { //异步注册 ExecutorService executor = executorRepository.getServiceExporterExecutor(); Future<?> future = executor.submit(() -> { sc.export(); }); asyncExportingFutures.add(future); } else { //同步注册 sc.export(); exportedServices.add(sc); } }); }
sc.export():service注册
public synchronized void export() { if (!shouldExport()) { //不需要注册,<dubbo:service export="false"/>新标签 官网好像没有更新 return; } if (bootstrap == null) { //BootStrap未启动,自动启动 bootstrap = DubboBootstrap.getInstance(); bootstrap.init(); } //检查并更新子设置 ① checkAndUpdateSubConfigs(); //初始化serviceMatadata属性 //版本 组名 接口类型 接口名称 实现接口的Bean实例 serviceMetadata.setVersion(version); serviceMetadata.setGroup(group); serviceMetadata.setDefaultGroup(group); serviceMetadata.setServiceType(getInterfaceClass()); serviceMetadata.setServiceInterfaceName(getInterface()); serviceMetadata.setTarget(getRef()); if (shouldDelay()) { //延迟注册 //<dubbo:service delay="1000"/> DELAY_EXPORT_EXECUTOR.schedule(this::doExport, getDelay(), TimeUnit.MILLISECONDS); } else { //直接注册 ② doExport(); } //注册后 ③ exported(); }
① checkAndUpdateSubConfigs():校验设置并更新一些默认设置
private void checkAndUpdateSubConfigs() { // 使用全局范围显式定义的默认配置 // <dubbo:provider/> <dubbo:protocol/> completeCompoundConfigs(); checkDefault(); checkProtocol(); // 初始化一些空设置 List<ConfigInitializer> configInitializers = ExtensionLoader.getExtensionLoader(ConfigInitializer.class) .getActivateExtension(URL.valueOf("configInitializer://"), (String[]) null); configInitializers.forEach(e -> e.initServiceConfig(this)); // if protocol is not injvm checkRegistry if (!isOnlyInJvm()) { //如果protocol不是内部调用(injvm) //检查registry设置 checkRegistry(); } //environment中的值覆盖service属性 this.refresh(); if (StringUtils.isEmpty(interfaceName)) { //interface属性必需 throw new IllegalStateException("<dubbo:service interface="" /> interface not allow null!"); } if (ref instanceof GenericService) { //如果实际Bean实现了GenericService接口,常用服务bean //interfaceClass = GenericService.class interfaceClass = GenericService.class; if (StringUtils.isEmpty(generic)) { generic = Boolean.TRUE.toString(); } } else { try { //不是GenericService接口类型,根据interfaceClass = Class.forName(interfaceName) interfaceClass = Class.forName(interfaceName, true, Thread.currentThread() .getContextClassLoader()); } catch (ClassNotFoundException e) { throw new IllegalStateException(e.getMessage(), e); } //检查接口方法都实现了 checkInterfaceAndMethods(interfaceClass, getMethods()); //bean实例不为空 checkRef(); generic = Boolean.FALSE.toString(); } if (local != null) { //配置<dubbo:service local="true"/>时 if ("true".equals(local)) { local = interfaceName + "Local"; } Class<?> localClass; try { //初始化代理类localClass = ClassforName(interfaceName+"Local") localClass = ClassUtils.forNameWithThreadContextClassLoader(local); } catch (ClassNotFoundException e) { throw new IllegalStateException(e.getMessage(), e); } if (!interfaceClass.isAssignableFrom(localClass)) { throw new IllegalStateException("The local implementation class " + localClass.getName() + " not implement interface " + interfaceName); } } if (stub != null) { //配置<dubbo:service local="true"/>时 if ("true".equals(stub)) { stub = interfaceName + "Stub"; } Class<?> stubClass; try { //初始化代理类stubClass = ClassforName(interfaceName+"Local") stubClass = ClassUtils.forNameWithThreadContextClassLoader(stub); } catch (ClassNotFoundException e) { throw new IllegalStateException(e.getMessage(), e); } if (!interfaceClass.isAssignableFrom(stubClass)) { throw new IllegalStateException("The stub implementation class " + stubClass.getName() + " not implement interface " + interfaceName); } } //检查若配置了local或stub,localClass或stubClass必须是interfaceClass的子类 checkStubAndLocal(interfaceClass); ConfigValidationUtils.checkMock(interfaceClass, this); //检查serviceconfig的属性 ConfigValidationUtils.validateServiceConfig(this); //配置后置处理器ConfigPostProcess,类似于BeanPostProcessor postProcessConfig(); }
② doExport():准备url,然后注册
/* org.apache.dubbo.config.ServiceConfig#doExport */ protected synchronized void doExport() { if (unexported) { throw new IllegalStateException("The service " + interfaceClass.getName() + " has already unexported!"); } //已注册的直接返回 if (exported) { return; } exported = true; if (StringUtils.isEmpty(path)) { //设置path默认值为接口名 path = interfaceName; } doExportUrls(); } private void doExportUrls() { //前面创建服务仓库ServiceRepository ServiceRepository repository = ApplicationModel.getServiceRepository(); //将Service注册到服务仓库ServiceRepository的services中 ServiceDescriptor serviceDescriptor = repository.registerService(getInterfaceClass()); //将Service注册到服务仓库ServiceRepository的providers中 repository.registerProvider( getUniqueServiceName(), ref, serviceDescriptor, this, serviceMetadata ); //生成registryURLs格式如下 // registry://mcip:2291/org.apache.dubbo.registry.RegistryService?application=dubbo-demo&backup=mcip:2292,mcip:2293&dubbo=2.0.2&pid=13252®istry=zookeeper&release=2.7.5×tamp=1584191484814 List<URL> registryURLs = ConfigValidationUtils.loadRegistries(this, true); //<dubbo:protocol name="dubbo" port="${dubbo.port}" /> for (ProtocolConfig protocolConfig : protocols) { //服务路径=protocol的contexpath属性+service的path+group+version String pathKey = URL.buildKey(getContextPath(protocolConfig) .map(p -> p + "/" + path) .orElse(path), group, version); // 如果指定了特殊路径,再次注入到服务仓库ServiceRepository的services中, // 未指定同名覆盖 repository.registerService(pathKey, interfaceClass); // TODO, uncomment this line once service key is unified //设置到serviceMetadata中 serviceMetadata.setServiceKey(pathKey); doExportUrlsFor1Protocol(protocolConfig, registryURLs); } } private void doExportUrls() { //前面创建服务仓库ServiceRepository ServiceRepository repository = ApplicationModel.getServiceRepository(); //将Service注册到服务仓库ServiceRepository的services中 ServiceDescriptor serviceDescriptor = repository.registerService(getInterfaceClass()); //将Service注册到服务仓库ServiceRepository的providers中 repository.registerProvider( getUniqueServiceName(), ref, serviceDescriptor, this, serviceMetadata ); //生成registryURLs格式如下 // registry://mcip:2291/org.apache.dubbo.registry.RegistryService?application=dubbo-demo&backup=mcip:2292,mcip:2293&dubbo=2.0.2&pid=13252®istry=zookeeper&release=2.7.5×tamp=1584191484814 List<URL> registryURLs = ConfigValidationUtils.loadRegistries(this, true); //<dubbo:protocol name="dubbo" port="${dubbo.port}" /> for (ProtocolConfig protocolConfig : protocols) { //服务路径=protocol的contexpath属性+service的path+group+version String pathKey = URL.buildKey(getContextPath(protocolConfig) .map(p -> p + "/" + path) .orElse(path), group, version); // 如果指定了特殊路径,再次注入到服务仓库ServiceRepository的services中, // 未指定同名覆盖 repository.registerService(pathKey, interfaceClass); // TODO, uncomment this line once service key is unified //设置到serviceMetadata中 serviceMetadata.setServiceKey(pathKey); //注册 doExportUrlsFor1Protocol(protocolConfig, registryURLs); } } private void doExportUrlsFor1Protocol(ProtocolConfig protocolConfig, List<URL> registryURLs) { String name = protocolConfig.getName(); if (StringUtils.isEmpty(name)) { //<dubbo:protocol name=""/>默认为dubbo name = DUBBO; } Map<String, String> map = new HashMap<String, String>(); //map.put("side","provider") map.put(SIDE_KEY, PROVIDER_SIDE); //map.put("release","2.7.5") dubbo版本号 //map.put("dubbo","2.0.2")大版本号 //map.put("pid",13252)进程号 //map.put("timestamp","1584192663652")时间戳 ServiceConfig.appendRuntimeParameters(map); AbstractConfig.appendParameters(map, getMetrics()); //map.put("application","dubbo-demo") 应用名 AbstractConfig.appendParameters(map, getApplication()); //map.put("module","") 模块名 AbstractConfig.appendParameters(map, getModule()); //map.put("dynamic","true") service的dynamic默认true,动态注册 //map.put("deprecated","false") service的deprecated默认false,作废标志 AbstractConfig.appendParameters(map, provider); AbstractConfig.appendParameters(map, protocolConfig); //map.put("interface","org.study.service.UserService") service的path 默认接口名 //map.put("generic","false") service的接口是否实现了GenericService AbstractConfig.appendParameters(map, this); MetadataReportConfig metadataReportConfig = getMetadataReportConfig(); if (metadataReportConfig != null && metadataReportConfig.isValid()) { map.putIfAbsent(METADATA_KEY, REMOTE_METADATA_STORAGE_TYPE); } //方法设置 if (CollectionUtils.isNotEmpty(getMethods())) { //...一般为空跳过 } if (ProtocolUtils.isGeneric(generic)) { //genericService设置 map.put(GENERIC_KEY, generic); map.put(METHODS_KEY, ANY_VALUE); } else { //接口版本号,跟随jar包 例如:1.0-SNAPSHOT String revision = Version.getVersion(interfaceClass, version); if (revision != null && revision.length() > 0) { map.put(REVISION_KEY, revision); } //接口的方法名数组 String[] methods = Wrapper.getWrapper(interfaceClass).getMethodNames(); if (methods.length == 0) { logger.warn("No method found in service interface " + interfaceClass.getName()); //空方法标志map.put("methods","*") map.put(METHODS_KEY, ANY_VALUE); } else { //方法数组字符串map.put("methods","insert,update") map.put(METHODS_KEY, StringUtils.join(new HashSet<String>(Arrays.asList(methods)), ",")); } } /** * Service的token验证 */ if(ConfigUtils.isEmpty(token) && provider != null) { token = provider.getToken(); } if (!ConfigUtils.isEmpty(token)) { if (ConfigUtils.isDefault(token)) { map.put(TOKEN_KEY, UUID.randomUUID().toString()); } else { map.put(TOKEN_KEY, token); } } //map放入到serviceMetadata中 serviceMetadata.getAttachments().putAll(map); // 获取协议host,默认获取本机ip <dubbo:protocol host="" /> String host = findConfigedHosts(protocolConfig, registryURLs, map); //获取协议port,dubbo默认20880 <dubbo:protocol port="" /> Integer port = findConfigedPorts(protocolConfig, name, map); //生成url格式如下 //dubbo://192.168.56.1:20880/org.study.service.UserService?anyhost=true&application=dubbo-demo&bind.ip=192.168.56.1&bind.port=20880&deprecated=false&dubbo=2.0.2&dynamic=true&generic=false&interface=org.study.service.UserService&methods=getUserById,update,insert,transactionalTest,getUserByUserId,delete&pid=13252&release=2.7.5&revision=1.0-SNAPSHOT&side=provider×tamp=1584192937036 URL url = new URL(name, host, port, getContextPath(protocolConfig).map(p -> p + "/" + path).orElse(path), map); // You can customize Configurator to append extra parameters if (ExtensionLoader.getExtensionLoader(ConfiguratorFactory.class) .hasExtension(url.getProtocol())) { url = ExtensionLoader.getExtensionLoader(ConfiguratorFactory.class) .getExtension(url.getProtocol()).getConfigurator(url).configure(url); } //获取作用域scope属性 String scope = url.getParameter(SCOPE_KEY); // scope == "none",不注册,一般为null if (!SCOPE_NONE.equalsIgnoreCase(scope)) { // export to local if the config is not remote (export to remote only when config is remote) if (!SCOPE_REMOTE.equalsIgnoreCase(scope)) { //scope != "remote" ,注册到本地,一般为null会注册到本地 exportLocal(url); } // export to remote if the config is not local (export to local only when config is local) if (!SCOPE_LOCAL.equalsIgnoreCase(scope)) { //scope != "local" ,注册到注册表,一般为null会注册到注册表 if (CollectionUtils.isNotEmpty(registryURLs)) { for (URL registryURL : registryURLs) { //if protocol is only injvm ,not register if (LOCAL_PROTOCOL.equalsIgnoreCase(url.getProtocol())) { //injvm,内部调用不注册 continue; } //url存在dynamic保留,不存在赋值为registryURL的dynamic属性值 url = url.addParameterIfAbsent(DYNAMIC_KEY, registryURL.getParameter(DYNAMIC_KEY)); //监控的url URL monitorUrl = ConfigValidationUtils.loadMonitor(this, registryURL); if (monitorUrl != null) { url = url.addParameterAndEncoded(MONITOR_KEY, monitorUrl.toFullString()); } if (logger.isInfoEnabled()) { if (url.getParameter(REGISTER_KEY, true)) { logger.info("Register dubbo service " + interfaceClass.getName() + " url " + url + " to registry " + registryURL); } else { logger.info("Export dubbo service " + interfaceClass.getName() + " to url " + url); } } // provider代理属性 一般为null String proxy = url.getParameter(PROXY_KEY); if (StringUtils.isNotEmpty(proxy)) { registryURL = registryURL.addParameter(PROXY_KEY, proxy); } //创建一个AbstractProxyInvoker的子类实例new AbstractProxyInvoker(ref, interfaceClass,rul) Invoker<?> invoker = PROXY_FACTORY.getInvoker(ref, (Class) interfaceClass, registryURL.addParameterAndEncoded(EXPORT_KEY, url.toFullString())); //包装器 DelegateProviderMetaDataInvoker wrapperInvoker = new DelegateProviderMetaDataInvoker(invoker, this); //默认DubboProtocol.export注册到远程注册表zookeeper中 Exporter<?> exporter = PROTOCOL.export(wrapperInvoker); exporters.add(exporter); } } else { if (logger.isInfoEnabled()) { logger.info("Export dubbo service " + interfaceClass.getName() + " to url " + url); } Invoker<?> invoker = PROXY_FACTORY.getInvoker(ref, (Class) interfaceClass, url); DelegateProviderMetaDataInvoker wrapperInvoker = new DelegateProviderMetaDataInvoker(invoker, this); Exporter<?> exporter = PROTOCOL.export(wrapperInvoker); exporters.add(exporter); } /** * @since 2.7.0 * ServiceData Store */ WritableMetadataService metadataService = WritableMetadataService.getExtension(url.getParameter(METADATA_KEY, DEFAULT_METADATA_STORAGE_TYPE)); if (metadataService != null) { metadataService.publishServiceDefinition(url); } } } this.urls.add(url); }
Exporter<?> exporter = PROTOCOL.export(wrapperInvoker):注册服务到zookeeper
PROTOCOL是javassist生成的protocol的代理对象,下面是代理对象的类,代理的是RegistryProtocol而不是DubboProtocol
public class Protocol$Adaptive implements org.apache.dubbo.rpc.Protocol { public void destroy() { throw new UnsupportedOperationException("The method public abstract void org.apache.dubbo.rpc.Protocol.destroy() of interface org.apache.dubbo.rpc.Protocol is not adaptive method!"); } public int getDefaultPort() { throw new UnsupportedOperationException("The method public abstract int org.apache.dubbo.rpc.Protocol.getDefaultPort() of interface org.apache.dubbo.rpc.Protocol is not adaptive method!"); } public org.apache.dubbo.rpc.Exporter export(org.apache.dubbo.rpc.Invoker arg0) throws org.apache.dubbo.rpc.RpcException { if (arg0 == null) throw new IllegalArgumentException("org.apache.dubbo.rpc.Invoker argument == null"); if (arg0.getUrl() == null) throw new IllegalArgumentException("org.apache.dubbo.rpc.Invoker argument getUrl() == null"); //debug : invoker.getUrl()=registry://mcip:2291/org.apache.dubbo.registry.RegistryService?application=dubbo-demo&backup=mcip:2292,mcip:2293&dubbo=2.0.2&export=dubbo%3A%2F%2F192.168.56.1%3A20880%2Forg.study.service.UserService%3Fanyhost%3Dtrue%26application%3Ddubbo-demo%26bind.ip%3D192.168.56.1%26bind.port%3D20880%26deprecated%3Dfalse%26dubbo%3D2.0.2%26dynamic%3Dtrue%26generic%3Dfalse%26interface%3Dorg.study.service.UserService%26methods%3DgetUserById%2Cupdate%2Cinsert%2CtransactionalTest%2CgetUserByUserId%2Cdelete%26pid%3D12956%26release%3D2.7.5%26revision%3D1.0-SNAPSHOT%26side%3Dprovider%26timestamp%3D1584262152345&pid=12956®istry=zookeeper&release=2.7.5×tamp=1584262152342 org.apache.dubbo.common.URL url = arg0.getUrl(); //debug:url.getProtocol() = "registry" //根据META_INF/dubbo/internal/org.apache.dubbo.rpc.protocol文件 //registry=org.apache.dubbo.registry.integration.RegistryProtocol //一直以为是DubboProtocol,但是DubboProtocol中没有注册到zookeeper的逻辑 String extName = (url.getProtocol() == null ? "dubbo" : url.getProtocol()); if (extName == null) throw new IllegalStateException("Failed to get extension (org.apache.dubbo.rpc.Protocol) name from url (" + url.toString() + ") use keys([protocol])"); org.apache.dubbo.rpc.Protocol extension = (org.apache.dubbo.rpc.Protocol) ExtensionLoader.getExtensionLoader(org.apache.dubbo.rpc.Protocol.class).getExtension(extName); return extension.export(arg0); } public org.apache.dubbo.rpc.Invoker refer(java.lang.Class arg0, org.apache.dubbo.common.URL arg1) throws org.apache.dubbo.rpc.RpcException { if (arg1 == null) throw new IllegalArgumentException("url == null"); org.apache.dubbo.common.URL url = arg1; String extName = (url.getProtocol() == null ? "dubbo" : url.getProtocol()); if (extName == null) throw new IllegalStateException("Failed to get extension (org.apache.dubbo.rpc.Protocol) name from url (" + url.toString() + ") use keys([protocol])"); org.apache.dubbo.rpc.Protocol extension = (org.apache.dubbo.rpc.Protocol) ExtensionLoader.getExtensionLoader(org.apache.dubbo.rpc.Protocol.class).getExtension(extName); return extension.refer(arg0, arg1); } public java.util.List getServers() { throw new UnsupportedOperationException("The method public default java.util.List org.apache.dubbo.rpc.Protocol.getServers() of interface org.apache.dubbo.rpc.Protocol is not adaptive method!"); } }
RegistryProtocol.export():远程注册,并Map<url,Service>容器
/* org.apache.dubbo.registry.integration.RegistryProtocol#export */ public <T> Exporter<T> export(final Invoker<T> originInvoker) throws RpcException { //注册url,zookeeper //zookeeper://mcip:2291/org.apache.dubbo.registry.RegistryService?application=dubbo-demo&backup=mcip:2292,mcip:2293&dubbo=2.0.2&export=dubbo%3A%2F%2F192.168.56.1%3A20880%2Forg.study.service.UserService%3Fanyhost%3Dtrue%26application%3Ddubbo-demo%26bind.ip%3D192.168.56.1%26bind.port%3D20880%26deprecated%3Dfalse%26dubbo%3D2.0.2%26dynamic%3Dtrue%26generic%3Dfalse%26interface%3Dorg.study.service.UserService%26methods%3DgetUserById%2Cupdate%2Cinsert%2CtransactionalTest%2CgetUserByUserId%2Cdelete%26pid%3D12956%26release%3D2.7.5%26revision%3D1.0-SNAPSHOT%26side%3Dprovider%26timestamp%3D1584262152345&pid=12956&release=2.7.5×tamp=1584262152342 URL registryUrl = getRegistryUrl(originInvoker); // 暴露服务的url //dubbo://192.168.56.1:20880/org.study.service.UserService?anyhost=true&application=dubbo-demo&bind.ip=192.168.56.1&bind.port=20880&deprecated=false&dubbo=2.0.2&dynamic=true&generic=false&interface=org.study.service.UserService&methods=getUserById,update,insert,transactionalTest,getUserByUserId,delete&pid=12956&release=2.7.5&revision=1.0-SNAPSHOT&side=provider×tamp=1584262152345 URL providerUrl = getProviderUrl(originInvoker); // 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. //生成最终url //provider://192.168.56.1:20880/org.study.service.UserService?anyhost=true&application=dubbo-demo&bind.ip=192.168.56.1&bind.port=20880&category=configurators&check=false&deprecated=false&dubbo=2.0.2&dynamic=true&generic=false&interface=org.study.service.UserService&methods=getUserById,update,insert,transactionalTest,getUserByUserId,delete&pid=12956&release=2.7.5&revision=1.0-SNAPSHOT&side=provider×tamp=1584262152345 final URL overrideSubscribeUrl = getSubscribedOverrideUrl(providerUrl); //url与service绑定,放入容器中,远程调用时根据url找到serviceimpl final OverrideListener overrideSubscribeListener = new OverrideListener(overrideSubscribeUrl, originInvoker); overrideListeners.put(overrideSubscribeUrl, overrideSubscribeListener); providerUrl = overrideUrlWithConfig(providerUrl, overrideSubscribeListener); //注册invoker到本地dubbo.expo
//调用DubboProtocol.export,其中openServer开启netty监听,这个地方不清楚,以后研究netty后再回来看 final ExporterChangeableWrapper<T> exporter = doLocalExport(originInvoker, providerUrl); // 最终的注册到zookeeper 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); if (register) { //服务注册 // 以zookeeper为例,建立一个znode // /dubbo/org.study.service.UserDubboService2/providers/dubbo%3A%2F%2F192.168.56.1%3A20880%2Forg.study.service.UserDubboService2%3Fanyhost%3Dtrue%26application%3Ddubbo-demo%26deprecated%3Dfalse%26dubbo%3D2.0.2%26dynamic%3Dtrue%26generic%3Dfalse%26interface%3Dorg.study.service.UserDubboService2%26methods%3DgetUserByUserId%26pid%3D1376%26release%3D2.7.5%26revision%3D1.0-SNAPSHOT%26side%3Dprovider%26timestamp%3D1584271781245 register(registryUrl, registeredProviderUrl); } // 这里是注册目录节点 // /dubbo/org.study.service.UserDubboService2/configurators registry.subscribe(overrideSubscribeUrl, overrideSubscribeListener); //记录registerUrl与subscribeUrl exporter.setRegisterUrl(registeredProviderUrl); exporter.setSubscribeUrl(overrideSubscribeUrl); //确认注册完 notifyExport(exporter); //Ensure that a new exporter instance is returned every time export return new DestroyableExporter<>(exporter); }
总结:
service主要作用就是在注册表注册,例如最终在zookeeper目录结构建立节点;然后本地保存<url,service>映射关系