Dubbo源码解析之服务的导出

本文详细解析了Dubbo服务导出的过程,包括从Spring容器发布刷新事件开始的前置工作,服务导出到本地和远程,以及向注册中心注册服务。重点介绍了Invoker的核心角色、DubboProtocol的export()方法,NettyServer的创建,以及服务注册在FailbackRegistry中的实现。文章指出,尽管服务注册不是必需的,但对于Dubbo来说是必要的。
摘要由CSDN通过智能技术生成

Dubbo服务的导出

Dubbo 服务导出过程始于 Spring 容器发布刷新事件,Dubbo 在接收到事件后,会立即执行服务导出逻辑。整个逻辑大致可分为三个部分,第一部分是前置工作,主要用于检查参数,组装 URL。第二部分是导出服务,包含导出服务到本地 (JVM),和导出服务到远程两个过程。第三部分是向注册中心注册服务,用于服务发现。
下边是Dubbo提供的一张服务导出的时序图,从图中我们可以大概的了解到Dubbo导出过程:

在这里插入图片描述
下边我们大概了解一下源码的导出过程:当DubboBootstrap启动后进行服务的进行导出发起的

//DubboBootstrap.java
    public DubboBootstrap start() {
   
        if (started.compareAndSet(false, true)) {
   
            ready.set(false);
            initialize();
            if (logger.isInfoEnabled()) {
   
                logger.info(NAME + " is starting...");
            }
            // 1. export Dubbo Services
            exportServices(); //调用ServiceConfig.export()导出服务
               ···
}

下边我们看服务Invoker的导出过程

public synchronized void export() {
   
        if (!shouldExport()) {
   
            return;
        }

        if (bootstrap == null) {
   
            bootstrap = DubboBootstrap.getInstance();
            bootstrap.initialize();
        }

        checkAndUpdateSubConfigs();

        //init serviceMetadata
        serviceMetadata.setVersion(getVersion());
        serviceMetadata.setGroup(getGroup());
        serviceMetadata.setDefaultGroup(getGroup());
        serviceMetadata.setServiceType(getInterfaceClass());
        serviceMetadata.setServiceInterfaceName(getInterface());
        serviceMetadata.setTarget(getRef());

        if (shouldDelay()) {
    //如果延迟的话使用任务延迟导出
            DELAY_EXPORT_EXECUTOR.schedule(this::doExport, getDelay(), TimeUnit.MILLISECONDS);
        } else {
   
            doExport(); //发起导出
        }

        exported(); //发送ServiceConfigExportedEvent事件
    }

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 = interfaceName;
        }
        doExportUrls(); //导出操作
    }

 private void doExportUrls() {
   
        //获取注册中心信息
        ServiceRepository repository = ApplicationModel.getServiceRepository();
        ServiceDescriptor serviceDescriptor = repository.registerService(getInterfaceClass());
        repository.registerProvider(
                getUniqueServiceName(),
                ref,
                serviceDescriptor,
                this,
                serviceMetadata
        );

        List<URL> registryURLs = ConfigValidationUtils.loadRegistries(this, true);

        for (ProtocolConfig protocolConfig : protocols) {
    //多协议导出
            String pathKey = URL.buildKey(getContextPath(protocolConfig)
                    .map(p -> p + "/" + path)
                    .orElse(path), group, version);
            // In case user specified path, register service one more time to map it to path.
            repository.registerService(pathKey, interfaceClass);
            // TODO, uncomment this line once service key is unified
            serviceMetadata.setServiceKey(pathKey);
            doExportUrlsFor1Protocol(protocolConfig, registryURLs); //根据协议导出到注册中心
        }
    }

private void doExportUrlsFor1Protocol(ProtocolConfig protocolConfig, List<URL> registryURLs) {
   
        String name = protocolConfig.getName();
        if (StringUtils.isEmpty(name)) {
   
            name = DUBBO;
        }

        Map<String, String> map = new HashMap<String, String>(); //构建参数映射集合
       //将所有的服务信息放入到map中,包含
           ……
        //init serviceMetadata attachments
        serviceMetadata.getAttachments().putAll(map);

        // export service
        String host = findConfigedHosts(protocolConfig, registryURLs, map);
        Integer port = findConfigedPorts(protocolConfig, name, map);
        //Dubbo中URL 是 Dubbo 配置的载体,通过 URL 可让 Dubbo 的各种配置在各个模块之间传递。
        //组装 URL感兴趣的同学可以自行查查看源码
        URL url = new URL(name, host, port, getContextPath(protocolConfig).map(p -> p + "/" + path).orElse(path), map);
        
            ……
        Invoker<?> invoker = PROXY_FACTORY.getInvoker(ref, (Class) interfaceClass
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值