Dubbo源码分析之三:服务的暴露
来源:互联网 发布:百乐淘宝旗舰店 编辑:程序博客网 时间:2024/04/30 22:59
服务的暴露主要集中在 ServiceBean,ServiceConfig 中。类图如下:
先从ApplicationContextAware接口的setApplicationContext 开始
主要是一些监听器兼容性处理
public void setApplicationContext(ApplicationContext applicationContext) { this.applicationContext = applicationContext; // 将applicationContext缓存起来 SpringExtensionFactory.addApplicationContext(applicationContext); // 下面主要是兼容老版本spring的Listener的处理 if (applicationContext != null) { SPRING_CONTEXT = applicationContext; try { Method method = applicationContext.getClass().getMethod("addApplicationListener", new Class<?>[]{ApplicationListener.class}); // 兼容Spring2.0.1 method.invoke(applicationContext, new Object[] {this}); supportedApplicationListener = true; } catch (Throwable t) { if (applicationContext instanceof AbstractApplicationContext) { try { Method method = AbstractApplicationContext.class.getDeclaredMethod("addListener", new Class<?>[]{ApplicationListener.class}); // 兼容Spring2.0.1 if (! method.isAccessible()) { method.setAccessible(true); } method.invoke(applicationContext, new Object[] {this}); supportedApplicationListener = true; } catch (Throwable t2) { } } } } }
ApplicationListener 的实现,启动完成,暴露服务:
public void onApplicationEvent(ApplicationEvent event) { if (ContextRefreshedEvent.class.getName().equals(event.getClass().getName())) { if (isDelay() && ! isExported() && ! isUnexported()) { if (logger.isInfoEnabled()) { logger.info("The service ready on spring started. service: " + getInterface()); } export(); // 在系统启动完成后暴露服务 } } }
在afterPropertiesSet 方法中,实现于InitializingBean。
主要是在暴露前的准备工作
public void afterPropertiesSet() throws Exception { if (getProvider() == null) { // 在spring中查找ProviderConfig Map<String, ProviderConfig> providerConfigMap = applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, ProviderConfig.class, false, false); if (providerConfigMap != null && providerConfigMap.size() > 0) { Map<String, ProtocolConfig> protocolConfigMap = applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, ProtocolConfig.class, false, false); if ((protocolConfigMap == null || protocolConfigMap.size() == 0) && providerConfigMap.size() > 1) { // 兼容旧版本 List<ProviderConfig> providerConfigs = new ArrayList<ProviderConfig>(); for (ProviderConfig config : providerConfigMap.values()) { if (config.isDefault() != null && config.isDefault().booleanValue()) { providerConfigs.add(config); } } if (providerConfigs.size() > 0) { setProviders(providerConfigs); } } else { ProviderConfig providerConfig = null; for (ProviderConfig config : providerConfigMap.values()) { if (config.isDefault() == null || config.isDefault().booleanValue()) { if (providerConfig != null) { // 一个应用只能有一个providerConfig 提供者 throw new IllegalStateException("Duplicate provider configs: " + providerConfig + " and " + config); } providerConfig = config; } } if (providerConfig != null) { setProvider(providerConfig); } } } } if (getApplication() == null && (getProvider() == null || getProvider().getApplication() == null)) { //在spring中查找ApplicationConfig Map<String, ApplicationConfig> applicationConfigMap = applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, ApplicationConfig.class, false, false); if (applicationConfigMap != null && applicationConfigMap.size() > 0) { ApplicationConfig applicationConfig = null; for (ApplicationConfig config : applicationConfigMap.values()) { if (config.isDefault() == null || config.isDefault().booleanValue()) { if (applicationConfig != null) { //也不能重复配置 throw new IllegalStateException("Duplicate application configs: " + applicationConfig + " and " + config); } applicationConfig = config; } } if (applicationConfig != null) { setApplication(applicationConfig); } } } if (getModule() == null && (getProvider() == null || getProvider().getModule() == null)) { // 在spring 中查找ModuleConfig Map<String, ModuleConfig> moduleConfigMap = applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, ModuleConfig.class, false, false); if (moduleConfigMap != null && moduleConfigMap.size() > 0) { ModuleConfig moduleConfig = null; for (ModuleConfig config : moduleConfigMap.values()) { if (config.isDefault() == null || config.isDefault().booleanValue()) { if (moduleConfig != null) { // 也不能重复 throw new IllegalStateException("Duplicate module configs: " + moduleConfig + " and " + config); } moduleConfig = config; } } if (moduleConfig != null) { setModule(moduleConfig); } } } if ((getRegistries() == null || getRegistries().size() == 0) && (getProvider() == null || getProvider().getRegistries() == null || getProvider().getRegistries().size() == 0) && (getApplication() == null || getApplication().getRegistries() == null || getApplication().getRegistries().size() == 0)) { // spring 中查找注册中心的配置 Map<String, RegistryConfig> registryConfigMap = applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, RegistryConfig.class, false, false); if (registryConfigMap != null && registryConfigMap.size() > 0) { List<RegistryConfig> registryConfigs = new ArrayList<RegistryConfig>(); for (RegistryConfig config : registryConfigMap.values()) { if (config.isDefault() == null || config.isDefault().booleanValue()) { registryConfigs.add(config); } } if (registryConfigs != null && registryConfigs.size() > 0) { super.setRegistries(registryConfigs); // 注册中心可以有多个 } } } if (getMonitor() == null && (getProvider() == null || getProvider().getMonitor() == null) && (getApplication() == null || getApplication().getMonitor() == null)) { Map<String, MonitorConfig> monitorConfigMap = applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, MonitorConfig.class, false, false); if (monitorConfigMap != null && monitorConfigMap.size() > 0) { MonitorConfig monitorConfig = null; for (MonitorConfig config : monitorConfigMap.values()) { if (config.isDefault() == null || config.isDefault().booleanValue()) { if (monitorConfig != null) { //监视器只能有一个 throw new IllegalStateException("Duplicate monitor configs: " + monitorConfig + " and " + config); } monitorConfig = config; } } if (monitorConfig != null) { setMonitor(monitorConfig); } } } if ((getProtocols() == null || getProtocols().size() == 0) && (getProvider() == null || getProvider().getProtocols() == null || getProvider().getProtocols().size() == 0)) { Map<String, ProtocolConfig> protocolConfigMap = applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, ProtocolConfig.class, false, false); if (protocolConfigMap != null && protocolConfigMap.size() > 0) { List<ProtocolConfig> protocolConfigs = new ArrayList<ProtocolConfig>(); for (ProtocolConfig config : protocolConfigMap.values()) { if (config.isDefault() == null || config.isDefault().booleanValue()) { protocolConfigs.add(config); } } if (protocolConfigs != null && protocolConfigs.size() > 0) { super.setProtocols(protocolConfigs); //protocolConfigs 通信协议可以有多个 } } } if (getPath() == null || getPath().length() == 0) { if (beanName != null && beanName.length() > 0 && getInterface() != null && getInterface().length() > 0 && beanName.startsWith(getInterface())) { setPath(beanName); //服务名称 } } if (! isDelay()) { export(); //没有延迟就会直接导出暴露,就算这里没暴露,onApplicationEvent中也会暴露 } }
export() 回调用doExport() 方法,doExport 做了很多检查工作:
protected synchronized void doExport() { 。。。// 省略 // 将调用 appendProperties 初始化provider // 先通过System.getProperty找,如果没找到,再在属性配置文件找 checkDefault(); 。。。 if (ref instanceof GenericService) { // 通用服务,提供动态性支持 interfaceClass = GenericService.class; if (StringUtils.isEmpty(generic)) { generic = Boolean.TRUE.toString();//通用服务标识 } } else { try {// 自定义服务 interfaceClass = Class.forName(interfaceName, true, Thread.currentThread() .getContextClassLoader()); } catch (ClassNotFoundException e) { throw new IllegalStateException(e.getMessage(), e); } // 检查接口与方法的合法性 // 其中有个异常提示语错误:<dubbo:service interface=\"" + interfaceClass.getName() + "\" ... ><dubbo:method name=\"\" ... /></<**dubbo:reference**> //dubbo:reference应为dubbo:service checkInterfaceAndMethods(interfaceClass, methods); checkRef(); //检查引用 generic = Boolean.FALSE.toString(); //通用服务标识 } if(local !=null){ if(local=="true"){ local=interfaceName+"Local"; } Class<?> localClass; try { localClass = ClassHelper.forNameWithThreadContextClassLoader(local); } catch (ClassNotFoundException e) { throw new IllegalStateException(e.getMessage(), e); } if(!interfaceClass.isAssignableFrom(localClass)){ throw new IllegalStateException("The local implemention class " + localClass.getName() + " not implement interface " + interfaceName); } } if(stub !=null){ if(stub=="true"){ stub=interfaceName+"Stub"; } Class<?> stubClass; try { stubClass = ClassHelper.forNameWithThreadContextClassLoader(stub); } catch (ClassNotFoundException e) { throw new IllegalStateException(e.getMessage(), e); } if(!interfaceClass.isAssignableFrom(stubClass)){ throw new IllegalStateException("The stub implemention class " + stubClass.getName() + " not implement interface " + interfaceName); } } // 配置application参数 /* * * 先通过System.getProperty找,如果没找到,再在属性配置文件找 * 通过 appendProperties()完成属性的配置 */ checkApplication(); // application 不能为空 checkRegistry(); // 配置注册中心,至少有一个。方式同上 checkProtocol(); // 配置协议,名称默认dubbo,方式同上 appendProperties(this); // 配置服务属性 //检查 local,stub是否存在,是否实现interfaceClass接口, //是否有指定的构造函数 /*并检查是否mock,有两种方式, 1 return xxx; 2 指定 mock 类 */ checkStubAndMock(interfaceClass); if (path == null || path.length() == 0) { path = interfaceName; } doExportUrls(); // 导出服务URL至注册中心 }
private void doExportUrls() { List<URL> registryURLs = loadRegistries(true); // 获得所有注册中心URL for (ProtocolConfig protocolConfig : protocols) { // 根据不同的协议分别导出 doExportUrlsFor1Protocol(protocolConfig, registryURLs); } }
// 获得所有注册中心URLprotected List<URL> loadRegistries(boolean provider) { //检查注册中心,包括从配置文件获取(dubbo.registry.address属性,以|分隔) checkRegistry(); List<URL> registryList = new ArrayList<URL>(); if (registries != null && registries.size() > 0) { for (RegistryConfig config : registries) { String address = config.getAddress(); if (address == null || address.length() == 0) { address = Constants.ANYHOST_VALUE; } // 从系统属性中获取注册中心信息 以;分隔 String sysaddress = System.getProperty("dubbo.registry.address"); if (sysaddress != null && sysaddress.length() > 0) { address = sysaddress; } if (address != null && address.length() > 0 && ! RegistryConfig.NO_AVAILABLE.equalsIgnoreCase(address)) { Map<String, String> map = new HashMap<String, String>(); appendParameters(map, application); //将application属性放入map appendParameters(map, config); //将config属性放入map map.put("path", RegistryService.class.getName()); map.put("dubbo", Version.getVersion()); map.put(Constants.TIMESTAMP_KEY, String.valueOf(System.currentTimeMillis())); if (ConfigUtils.getPid() > 0) { map.put(Constants.PID_KEY, String.valueOf(ConfigUtils.getPid())); } if (! map.containsKey("protocol")) { // 查询注册中心是否支持remote协议 // 后面会介绍dubbo是怎么发现注册中心的。 if (ExtensionLoader.getExtensionLoader(RegistryFactory.class).hasExtension("remote")) { map.put("protocol", "remote"); } else { map.put("protocol", "dubbo"); } } //将地址与参数拼成url,address可能是以“;”分隔的。 List<URL> urls = UrlUtils.parseURLs(address, map); for (URL url : urls) { url = url.addParameter(Constants.REGISTRY_KEY, url.getProtocol()); url = url.setProtocol(Constants.REGISTRY_PROTOCOL); if ((provider && url.getParameter(Constants.REGISTER_KEY, true)) || (! provider && url.getParameter(Constants.SUBSCRIBE_KEY, true))) { registryList.add(url); } } } } } return registryList; }
关于注册中心的发现。针对上面的方法,调用关系为:
getExtensionLoader -〉hasExtension -〉getExtensionClass —>getExtensionClasses -> loadExtensionClasses
private Map<String, Class<?>> loadExtensionClasses() { // 获取type 上的SPI注解,确定 type 对应哪些名称。 // 例如:RegisterFactory 对应 dubbo final SPI defaultAnnotation = type.getAnnotation(SPI.class); if(defaultAnnotation != null) { String value = defaultAnnotation.value(); if(value != null && (value = value.trim()).length() > 0) { String[] names = NAME_SEPARATOR.split(value); if(names.length > 1) { throw new IllegalStateException("more than 1 default extension name on extension " + type.getName() + ": " + Arrays.toString(names)); } if(names.length == 1) cachedDefaultName = names[0]; } } Map<String, Class<?>> extensionClasses = new HashMap<String, Class<?>>(); // 重点,从不同的路径或得对应的扩展 loadFile(extensionClasses, DUBBO_INTERNAL_DIRECTORY); // META-INF/dubbo/internal/ loadFile(extensionClasses, DUBBO_DIRECTORY); // META-INF/dubbo/ loadFile(extensionClasses, SERVICES_DIRECTORY); // META-INF/services/ return extensionClasses; }
我们看一个例子: RegisterFactory
内容为:
zookeeper=com.alibaba.dubbo.registry.zookeeper.ZookeeperRegistryFactory
现在,我们再看一下doExportUrlsFor1Protocol 方法,是怎么注册服务的。
private void doExportUrlsFor1Protocol(ProtocolConfig protocolConfig, List<URL> registryURLs) { 。。。 //省略的部分主要是,参数检查,默认值得处理,以及注册需要的数据都存到一个Map中 String scope = url.getParameter(Constants.SCOPE_KEY); // 配置为none不暴露 if (! Constants.SCOPE_NONE.toString().equalsIgnoreCase(scope)) { //配置不是remote的情况下做本地暴露 (配置为remote,则表示只暴露远程服务) if (!Constants.SCOPE_REMOTE.toString().equalsIgnoreCase(scope)) { exportLocal(url); } //如果配置不是local则暴露为远程服务.(配置为local,则表示只暴露远程服务) if (! Constants.SCOPE_LOCAL.toString().equalsIgnoreCase(scope) ){ if (logger.isInfoEnabled()) { logger.info("Export dubbo service " + interfaceClass.getName() + " to url " + url); } if (registryURLs != null && registryURLs.size() > 0 && url.getParameter("register", true)) { for (URL registryURL : registryURLs) { url = url.addParameterIfAbsent("dynamic", registryURL.getParameter("dynamic")); URL monitorUrl = loadMonitor(registryURL); if (monitorUrl != null) { url = url.addParameterAndEncoded(Constants.MONITOR_KEY, monitorUrl.toFullString()); } if (logger.isInfoEnabled()) { logger.info("Register dubbo service " + interfaceClass.getName() + " url " + url + " to registry " + registryURL); } // 通过代理工厂获得一个调用者 // 关于proxyFactory实例,看下面的截图。默认SPI 名称为:javassist Invoker<?> invoker = proxyFactory.getInvoker(ref, (Class) interfaceClass, registryURL.addParameterAndEncoded(Constants.EXPORT_KEY, url.toFullString())); // 执行注册导出,这里使用了registry 协议 // 通过类似上面的方式找到com.alibaba.dubbo.registry.integration.RegistryProtocol // ProtocolListenerWrapper -> ProtocolFilterWrapper ->RegistryProtocol Exporter<?> exporter = protocol.export(invoker); exporters.add(exporter); } } else { Invoker<?> invoker = proxyFactory.getInvoker(ref, (Class) interfaceClass, url); Exporter<?> exporter = protocol.export(invoker); exporters.add(exporter); } } }}
再看看 RegistryProtocol.export 实现
public <T> Exporter<T> export(final Invoker<T> originInvoker) throws RpcException { //export invoker // 导出本地调用 final ExporterChangeableWrapper<T> exporter = doLocalExport(originInvoker); //registry provider // 注册器提供者。 // 假设使用zk,会通过ZookeeperRegistryFactory 获得 ZookeeperRegistry final Registry registry = getRegistry(originInvoker); final URL registedProviderUrl = getRegistedProviderUrl(originInvoker); // 注册提供者URL,注册中心会记录此信息 // 最终的注册动作 registry.register(registedProviderUrl); // 订阅override数据 // FIXME 提供者订阅时,会影响同一JVM即暴露服务,又引用同一服务的的场景,因为subscribed以服务名为缓存的key,导致订阅信息覆盖。 final URL overrideSubscribeUrl = getSubscribedOverrideUrl(registedProviderUrl); final OverrideListener overrideSubscribeListener = new OverrideListener(overrideSubscribeUrl); overrideListeners.put(overrideSubscribeUrl, overrideSubscribeListener); registry.subscribe(overrideSubscribeUrl, overrideSubscribeListener); //保证每次export都返回一个新的exporter实例 return new Exporter<T>() { public Invoker<T> getInvoker() { return exporter.getInvoker(); } public void unexport() { try { exporter.unexport(); } catch (Throwable t) { logger.warn(t.getMessage(), t); } try { registry.unregister(registedProviderUrl); } catch (Throwable t) { logger.warn(t.getMessage(), t); } try { overrideListeners.remove(overrideSubscribeUrl); registry.unsubscribe(overrideSubscribeUrl, overrideSubscribeListener); } catch (Throwable t) { logger.warn(t.getMessage(), t); } } }; }
registry.register -> FailbackRegistry.register -> ZookeeperRegistry.doRegister
protected void doRegister(URL url) { try { // 完成节点创建 zkClient.create(toUrlPath(url), url.getParameter(Constants.DYNAMIC_KEY, true)); } catch (Throwable e) { throw new RpcException("Failed to register " + url + " to zookeeper " + getUrl() + ", cause: " + e.getMessage(), e); } }
0 0
- Dubbo源码分析之三:服务的暴露
- Dubbo暴露服务和引用服务的实现源码分析
- Dubbo暴露服务和引用服务的实现源码分析
- dubbo源码学习(五)dubbo暴露服务的过程
- Dubbo/Dubbox的服务暴露(三)- 服务的注册
- [Dubbo源码分析]Dubbo暴露与引用
- Dubbo服务暴露的流程
- dubbo源码阅读笔记--暴露服务时序
- Dubbo注册dubbo服务的源码分析
- Dubbo源码分析之四:服务的调用
- Dubbo中暴露服务的过程解析
- Dubbo/Dubbox的服务暴露(一)
- dubbo暴露服务过程
- Dubbo服务再暴露
- dubbo扩展spring scheme 暴露服务提供者的源码跟踪演绎
- Dubbo源码分析系列-服务的发布
- Dubbo源码分析系列-服务的引用
- Dubbo源码分析(三):Dubbo之服务端(Service)
- linux环境上setuptools-20.7.0安装
- NYOJ 21 三个水杯(bfs,广搜)
- 百度地图开发(3)实现本地两点间步行导航
- AngularJs模块化指令02(模板放标签)
- 粗颗粒度权限控制
- Dubbo源码分析之三:服务的暴露
- 选课
- java的数组
- 【opencv】神经网络识别数字
- select函数详解
- csr8670 (1)
- QT QAxObject 复制Excel Sheet方法
- 星级评分RatingBar
- 知道这20个正则表达式,能让你少写1,000行代码