Dubbo 调用图解dubbo的调用图来自官网如下图共包含了5个模块Provider 服务提供方Registry 服务注册中心这里可以认为是zookeeperConsumer 服务使用方Container 服务提供方的容器Monitor 服务监控中心服务调用流程提供服务的容器启动之后把该服务提交给服务提供方服务提供方把该服务细节以约定的协议此处可认为是dubbo协议把IP、端口、服务名等等上报给服务注册中心由服务注册中心统一管理另外存在心跳检测便于及时了解服务健康情况服务均衡负责等也由其管理服务调用方从服务注册中心获取到一个可用的服务提供方的信息服务注册中心把合适的服务提供方的细节信息下发到调用方服务调用方持有服务提供方的调用信息可直连服务提供方进行invoke调用操作服务提供方以及服务调用方的调用情况在必备的情况下都可以定时上报到监控中心从而了解服务调用的数据统计情况接着把上述过程模块化细化出来如下图引入从spring解析xml开始我们能够很明显的查看到DubboNamespaceHandler文件javapublic class DubboNamespaceHandler extends NamespaceHandlerSupport implements ConfigurableSourceBeanMetadataElement { public DubboNamespaceHandler() { } public void init() { this.registerBeanDefinitionParser(application, new DubboBeanDefinitionParser(ApplicationConfig.class)); this.registerBeanDefinitionParser(module, new DubboBeanDefinitionParser(ModuleConfig.class)); this.registerBeanDefinitionParser(registry, new DubboBeanDefinitionParser(RegistryConfig.class)); this.registerBeanDefinitionParser(config-center, new DubboBeanDefinitionParser(ConfigCenterBean.class)); this.registerBeanDefinitionParser(metadata-report, new DubboBeanDefinitionParser(MetadataReportConfig.class)); this.registerBeanDefinitionParser(monitor, new DubboBeanDefinitionParser(MonitorConfig.class)); this.registerBeanDefinitionParser(metrics, new DubboBeanDefinitionParser(MetricsConfig.class)); this.registerBeanDefinitionParser(tracing, new DubboBeanDefinitionParser(TracingConfig.class)); this.registerBeanDefinitionParser(ssl, new DubboBeanDefinitionParser(SslConfig.class)); this.registerBeanDefinitionParser(provider, new DubboBeanDefinitionParser(ProviderConfig.class)); this.registerBeanDefinitionParser(consumer, new DubboBeanDefinitionParser(ConsumerConfig.class)); this.registerBeanDefinitionParser(protocol, new DubboBeanDefinitionParser(ProtocolConfig.class)); this.registerBeanDefinitionParser(service, new DubboBeanDefinitionParser(ServiceBean.class)); this.registerBeanDefinitionParser(reference, new DubboBeanDefinitionParser(ReferenceBean.class)); this.registerBeanDefinitionParser(annotation, new AnnotationBeanDefinitionParser()); } public BeanDefinition parse(Element element, ParserContext parserContext) { BeanDefinitionRegistry registry parserContext.getRegistry(); this.registerAnnotationConfigProcessors(registry); DubboSpringInitializer.initialize(parserContext.getRegistry()); BeanDefinition beanDefinition super.parse(element, parserContext); this.setSource(beanDefinition); return beanDefinition; } private void registerAnnotationConfigProcessors(BeanDefinitionRegistry registry) { AnnotationConfigUtils.registerAnnotationConfigProcessors(registry); } }在为外界暴露服务的时候常使用dubbo:service interfacecom.XXX refxXXX /再结合DubboBeanDefinitionParser类的parse细节可知服务暴露我们应该关注的类是ServiceBean.classServiceBean 介绍如下图是ServiceBean类的继承关系图右边圈出来的是关于dubbo的下面底部的是和spring有关的。很清楚的看到serviceBean也是一个可由Spring管理的很普通的bean通过BeanNameAware修改bean的名称ApplicationContextAware去获取Spring IOC的容器IntializingBean的afterPropertiesSet去自定义实现bean的实例对象ApplicationListener的onApplicationEvent接收各种事件DisposableBean的destroy去销毁bean右侧则和dubbo有关一层一层的config扩展实例化包含了在xml配置中的各种参数配置。属性属性是整个的服务暴露的这个ServiceBean包含的各种属性信息xml配置信息都会合并到这个属性中ServiceConfig 类javaprivate String interfaceName; // 接口类型 private Class? interfaceClass; private T ref; // 接口实现类引用 private String path; // 服务名称 private ListMethodConfig methods; // 方法配置 private ProviderConfig provider; // 提供方配置方法配置参数methods,一般情况下是没有设置的也就意味着该接口下的所有的方法都会被暴露出去如果设置了就意味着设置的方法才会被暴露出去。提供方配置provider也是负责服务暴露方的一些熟悉信息例如负载均衡等信息。AbstractServiceConfig 类javaprotected String version; // 服务版本 protected String group; // 服务分组 protected Boolean deprecated; // 服务是否已经deprecated protected Integer delay; // 延迟暴露 protected Boolean export; // 是否暴露 protected Integer weight; // 权重 protected String document; // 应用文档 protected Boolean dynamic; // 在注册中心上注册成动态的还是静态的服务 protected String token; // 是否使用令牌 protected String accesslog; // 访问日志 private Integer executes; // 允许执行请求数 protected ListProtocolConfig protocols; // 暴露的协议 private Boolean register; // 是否注册其中protocols就是常说的dubbo协议了这里指明list也就是意味着支持可以同时多种协议对外暴露AbstractInterfaceConfig 类javaprotected String local; // 服务接口的本地实现类名 protected String stub; // 服务接口的本地实现类名 protected MonitorConfig monitor; // 服务监控 protected String proxy; // 代理类型 protected String cluster; // 集群方式 protected String filter; // 过滤器 protected String listener; // 监听器 protected String owner; // 负责人 // 连接数限制,0表示共享连接否则为该服务独享连接数 protected Integer connections; protected String layer; // 连接数限制 protected ApplicationConfig application; // 应用信息 protected ModuleConfig module; // 模块信息 protected ListRegistryConfig registries; // 注册中心 private Integer callbacks; // callback实例个数限制 protected String onconnect; // 连接事件 protected String ondisconnect; // 断开事件 // 服务暴露或引用的scope,如果为local则表示只在当前JVM内查找. private String scope;注册中心registries应该是比较重要的属性信息了包含了注册中心的数据比如设置zk的相关属性信息后期暴露也主要是把服务按照约定的协议推送给注册中心。其他继承的类的属性更多的是涉及到系统管理、监控等层级的属性在此不做过多介绍了配置注入bean继承了IntializingBean那肯定就使用了afterPropertiesSet方法注意在运行到这个时候servicebean实例化是已经完成了的。javapublic void afterPropertiesSet() throws Exception { if (getProvider() null) { // 提供方为null MapString, ProviderConfig providerConfigMap applicationContext null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, ProviderConfig.class, false, false); // 此处的applicationContext就是通过继承ApplicationContextAware注入的Spring IOC容器 // 获取所有类型是ProviderConfig的bean信息 if (providerConfigMap ! null providerConfigMap.size() 0) { MapString, ProtocolConfig protocolConfigMap applicationContext null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, ProtocolConfig.class, false, false); // 获取ProtocolConfig if ((protocolConfigMap null || protocolConfigMap.size() 0) providerConfigMap.size() 1) { // 兼容旧版本 // 如果没有protocolconfig同时有providerconfig ListProviderConfig providerConfigs new ArrayListProviderConfig(); for (ProviderConfig config : providerConfigMap.values()) { if (config.isDefault() ! null config.isDefault().booleanValue()) { // config不为空而且是默认值 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) { throw new IllegalStateException(Duplicate provider configs: providerConfig and config); } providerConfig config; } } if (providerConfig ! null) { // 默认的只应该存在一个providerconfig信息 setProvider(providerConfig); } } } } if (getApplication() null (getProvider() null || getProvider().getApplication() null)) { MapString, 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) { // 填充ApplicationConfig信息 setApplication(applicationConfig); } } } if (getModule() null (getProvider() null || getProvider().getModule() null)) { MapString, 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) { // 填充ModuleConfig信息 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)) { MapString, RegistryConfig registryConfigMap applicationContext null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, RegistryConfig.class, false, false); if (registryConfigMap ! null registryConfigMap.size() 0) { ListRegistryConfig registryConfigs new ArrayListRegistryConfig(); 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)) { MapString, 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)) { MapString, ProtocolConfig protocolConfigMap applicationContext null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, ProtocolConfig.class, false, false); if (protocolConfigMap ! null protocolConfigMap.size() 0) { ListProtocolConfig protocolConfigs new ArrayListProtocolConfig(); for (ProtocolConfig config : protocolConfigMap.values()) { if (config.isDefault() null || config.isDefault().booleanValue()) { protocolConfigs.add(config); } } if (protocolConfigs ! null protocolConfigs.size() 0) { // 设置使用的协议 super.setProtocols(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(); } }在这一段代码中就是从Spring IOC容器中获取合适的bean注入到ServiceBean中例如使用的服务信息、服务注册中心、使用的协议、均衡负责的方式provider的loanBanance、监控等。暴露服务启动服务暴露其实就是export函数如果设置了延迟则会在ApplicationListener的事件中去暴露服务。javapublic void onApplicationEvent(ApplicationEvent event) { if (ContextRefreshedEvent.class.getName().equals(event.getClass().getName())) { // 当前事件是bean刷新结束 if (isDelay() ! isExported() ! isUnexported()) { // 是延期而且还没有暴富同时 没有 不希望 暴露服务 if (logger.isInfoEnabled()) { logger.info(The service ready on spring started. service: getInterface()); } // 跳转到ServiceConfig类中 export(); } } }ServiceConfig 类javapublic synchronized void export() { // 这里面的provider等信息都是之前注入的信息属性 if (provider ! null) { if (export null) { export provider.getExport(); } if (delay null) { delay provider.getDelay(); } } if (export ! null ! export.booleanValue()) { return; } if (delay ! null delay 0) { // 如果设置了延迟则设置成为守护线程睡眠延迟的时间数再执行暴露服务的任务 Thread thread new Thread(new Runnable() { public void run() { try { Thread.sleep(delay); } catch (Throwable e) { } doExport(); } }); thread.setDaemon(true); thread.setName(DelayExportServiceThread); thread.start(); } else { doExport(); } }在doExport方法中更多的是对一些数据的check操作随后来到了doExportUrls方法javaprivate void doExportUrls() { ListURL registryURLs loadRegistries(true); // 先获取注册中心的属性信息 for (ProtocolConfig protocolConfig : protocols) { // 存在多个暴露协议例如DUBBO、HTTP等依次对外暴露 doExportUrlsFor1Protocol(protocolConfig, registryURLs); } }服务注册中心属性获取AbstractInterfaceConfig 类javaprotected ListURL loadRegistries(boolean provider) { checkRegistry(); // 兼容老版本的dubbo服务 ListURL registryList new ArrayListURL(); if (registries ! null registries.size() 0) { // 循环遍历所有的注册中心配置 for (RegistryConfig config : registries) { String address config.getAddress(); // 注册中心的地址 if (address null || address.length() 0) { address Constants.ANYHOST_VALUE; // ANYHOST_VALUE 0.0.0.0 } String sysaddress System.getProperty(dubbo.registry.address); // 从系统属性中获取dubbo.registry.address的值 if (sysaddress ! null sysaddress.length() 0) { address sysaddress; // 真存在这个数据就替换掉之前的地址数据 } if (address ! null address.length() 0 ! RegistryConfig.NO_AVAILABLE.equalsIgnoreCase(address)) { // RegistryConfig.NO_AVAILABLE N\A,如果地址有效 MapString, String map new HashMapString, String(); appendParameters(map, application); appendParameters(map, config); map.put(path, RegistryService.class.getName()); map.put(dubbo, Version.getVersion()); map.put(Constants.TIMESTAMP_KEY, String.valueOf(System.currentTimeMillis())); // 把应用程序、当前的注册配置信息、以及dubbo、时间戳等信息注入到map中 if (ConfigUtils.getPid() 0) { // 获取当前服务的进程PID map.put(Constants.PID_KEY, String.valueOf(ConfigUtils.getPid())); } if (! map.containsKey(protocol)) { if (ExtensionLoader.getExtensionLoader(RegistryFactory.class).hasExtension(remote)) { // 如果在SPI中包含了支持remote的类则设置当前的协议为remote否则是dubbo map.put(protocol, remote); } else { map.put(protocol, dubbo);