美文网首页
Dubbo服务暴露流程

Dubbo服务暴露流程

作者: 王兴岭 | 来源:发表于2020-06-06 17:17 被阅读0次

官方图

image.png

源码分析

public class Provider {

  public static void main(String[] args) throws IOException {
    ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(
        new String[]{"classpath:spring/dubbo-provider.xml"});
    context.start();
    System.in.read(); // 按任意键退出
  }
}

当项目启动时,ClassPathXmlApplicationContext加载provider.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:dubbo="http://dubbo.apache.org/schema/dubbo"
  xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd">

  <dubbo:application name="hello-world-app"/>
  <dubbo:registry file="/Users/lemo-wu/output/dubbo.cache" protocol="zookeeper" address="localhost:2181?client=curator"/>
  <dubbo:protocol name="dubbo" port="20880"/>
  <dubbo:service group="test" version="1.0" interface="com.leimo.demo.DemoService" ref="demoService" timeout="100">
    <dubbo:method name="methodTimeout" timeout="1000"/>
  </dubbo:service>
  <bean id="demoService" class="com.leimo.demo.impl.DemoServiceImpl"/>
</beans>

dubbo:*是自定义命名空间,解析就交给DubboNamespaceHandler处理,当解析dubbo命名空间下的节点时会触发parse方法

@Override
    public BeanDefinition parse(Element element, ParserContext parserContext) {
        ...
        registerApplicationListeners(registry);
        ...
    }

registerApplicationListeners会注册DubboBootstrapApplicationListener监听器

private void registerApplicationListeners(BeanDefinitionRegistry registry) {
         ...
        registerBeans(registry, DubboBootstrapApplicationListener.class);
    }

DubboBootstrapApplicationListener监听器是在spring启动,关闭成功后触发的监听器,DubboBootstrapApplicationListener继承OneTimeExecutionApplicationContextEventListener抽象监听器类,根据名字可以知道此监听器只会触发一次

public class DubboBootstrapApplicationListener extends OneTimeExecutionApplicationContextEventListener
        implements Ordered {
    public static final String BEAN_NAME = "dubboBootstrapApplicationListener";

    private final DubboBootstrap dubboBootstrap;

    public DubboBootstrapApplicationListener() {
        this.dubboBootstrap = DubboBootstrap.getInstance();
    }

    @Override
    public void onApplicationContextEvent(ApplicationContextEvent event) {
        if (event instanceof ContextRefreshedEvent) {
            onContextRefreshedEvent((ContextRefreshedEvent) event);
        } else if (event instanceof ContextClosedEvent) {
            onContextClosedEvent((ContextClosedEvent) event);
        }
    }

    private void onContextRefreshedEvent(ContextRefreshedEvent event) {
        dubboBootstrap.start();
    }

    private void onContextClosedEvent(ContextClosedEvent event) {
        dubboBootstrap.stop();
    }
...
}

DubboBootstrapApplicationListener会在启动时调用DubboBootstrapstart方法启动dubbo.

public DubboBootstrap start() {
       ...
      // 1. export Dubbo Services
     exportServices();
      ...

我们只看下exportServices方法,其他无关代码忽略掉

private void exportServices() {
        //configManager.getServices() 获取的就是在provider.xml中配置的dubbo:service对应bean,类型是ServiceConfig
        configManager.getServices().forEach(sc -> {
            // TODO, compatible with ServiceConfig.export()
            ServiceConfig serviceConfig = (ServiceConfig) sc;
            serviceConfig.setBootstrap(this);

            if (exportAsync) { // 如果exportAsync为true就异步export,否则同步发布,默认为false
                ExecutorService executor = executorRepository.getServiceExporterExecutor();
                Future<?> future = executor.submit(() -> {
                    sc.export();
                    exportedServices.add(sc);
                });
                asyncExportingFutures.add(future);
            } else {
                sc.export();
                exportedServices.add(sc);
            }
        });
    }

exportAsync为false,所以走else分支,调用ServiceConfigexport方法
后续调用流程export -> doExport-> doExportUrls->doExportUrlsFor1Protocol

private void doExportUrlsFor1Protocol(ProtocolConfig protocolConfig, List<URL> registryURLs) {
  Invoker<?> invoker = PROXY_FACTORY.getInvoker(ref, (Class) interfaceClass,     
  registryURL.addParameterAndEncoded(EXPORT_KEY, url.toFullString()));
  DelegateProviderMetaDataInvoker wrapperInvoker = new DelegateProviderMetaDataInvoker(invoker, this);
  Exporter<?> exporter = PROTOCOL.export(wrapperInvoker);
 exporters.add(exporter);
}

PROXY_FACTORY 默认使用的是JavassistProxyFactory,通过JavassistProxyFactory获取Invoker对象,并最终通过PROTOCOL export出去, 值得一提的是PROXY_FACTORY, PROTOCOL使用的是SPI技术

相关文章

网友评论

      本文标题:Dubbo服务暴露流程

      本文链接:https://www.haomeiwen.com/subject/aekzzhtx.html