Dubbo源码分析1:生产者启动分析

本文涉及的产品
服务治理 MSE Sentinel/OpenSergo,Agent数量 不受限
云原生网关 MSE Higress,422元/月
注册配置 MSE Nacos/ZooKeeper,118元/月
简介: Dubbo源码分析

个人学习Dubbo使用,若有不足,欢迎指正

1. 项目准备

使用官方quick-start,工程源码见lucas-rpc-dubbo

1.1. 配置

1.1.1. pom配置

<!-- dubbo -->
<dependency>
  <groupId>com.alibaba</groupId>
  <artifactId>dubbo</artifactId>
  <version>2.6.2</version>
</dependency>
<!-- dubbo注册中心,这里使用zookeeper -->
<dependency>
  <groupId>org.apache.zookeeper</groupId>
  <artifactId>zookeeper</artifactId>
  <version>3.4.9</version>
</dependency>
<!-- zookeeper client,curator、zkclient选其一即可 -->
<!-- curator -->
<dependency>
  <groupId>org.apache.curator</groupId>
  <artifactId>curator-recipes</artifactId>
  <version>2.12.0</version>
</dependency>
<!-- zkclient -->
<dependency>
  <groupId>com.101tec</groupId>
  <artifactId>zkclient</artifactId>
  <version>0.10</version>
</dependency>
<!-- Spring依赖,版本视情况而定 -->
<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-context</artifactId>
  <version>5.0.8.RELEASE</version>
</dependency>
<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-beans</artifactId>
  <version>5.0.8.RELEASE</version>
</dependency>
<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-web</artifactId>
  <version>5.0.8.RELEASE</version>
</dependency>
<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-core</artifactId>
  <version>5.0.8.RELEASE</version>
</dependency>
<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-test</artifactId>
  <version>5.0.8.RELEASE</version>
</dependency>

1.1.2. 生产者xml配置

dubbo-demo-provider.xml

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

    <!-- 生产者的应用程序名称,用于跟踪依赖关系 -->
    <dubbo:application name="demo-provider"/>

    <!-- 使用zookeeper注册中心服务 -->
    <dubbo:registry address="zookeeper://127.0.0.1:2181?client=curator"/>

    <!-- 使用dubbo协议在20880端口暴露服务 -->
    <dubbo:protocol name="dubbo" port="20880"/>

    <!-- 服务实现,与常规本地bean一样 -->
    <bean id="demoService" class="me.lucas.kits.rpc.dubbo.provider.DemoServiceImpl"/>

    <!-- 声明要暴露的服务接口 -->
    <dubbo:service interface="me.lucas.kits.rpc.dubbo.provider.DemoService" ref="demoService" />
</beans>

1.1.3. 配置覆盖策略

dubbo配置覆盖]遵循以下逻辑:

  1. 优先使用JVM参数
  2. 其次使用XML配置
  3. 最后使用配置文件配置

dubbo配置覆盖

1.2. 生产者代码

1.2.1. 接口(api)

package me.lucas.kits.rpc.dubbo.api;

/**
 * Created by zhangxin on 2018/9/5-下午8:16.
 *
 * @author zhangxin
 * @version 1.0
 */
public interface DemoService {
    String sayHello(String name);
}

1.2.2. 实现

package me.lucas.kits.rpc.dubbo.provider;

import me.lucas.kits.rpc.dubbo.api.DemoService;
import org.springframework.stereotype.Service;

/**
 * Created by zhangxin on 2018/9/5-下午8:16.
 *
 * @author zhangxin
 * @version 1.0
 */
@Service
public class DemoServiceImpl implements DemoService {
    @Override
    public String sayHello(String name) {
        return "Hello " + name;
    }
}

1.2.3. 程序入口

package me.lucas.kits.rpc.dubbo;

import com.alibaba.dubbo.config.spring.context.annotation.DubboComponentScan;
import java.io.IOException;
import lombok.extern.slf4j.Slf4j;
import me.lucas.kits.rpc.dubbo.Provider.ProviderConfig;
import me.lucas.kits.rpc.dubbo.api.DemoService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ImportResource;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;

/**
 * Created by zhangxin on 2018/9/4-下午9:03.
 *
 * @author zhangxin
 * @version 1.0
 */
@Slf4j
@RunWith(SpringJUnit4ClassRunner.class)
//此注解用来加载配置ApplicationContext
@ContextConfiguration(classes = { ProviderConfig.class })
@WebAppConfiguration
public class Provider {

    @Autowired(required = false)
    private DemoService demoService;

    @Test
    public void provider() throws IOException {
        //        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(new String[] {"http://10.20.160.198/wiki/display/dubbo/provider.xml"});
        //        context.start();
        System.in.read(); // 按任意键退出
    }

    @Configuration
    @ImportResource(value = { "classpath:spring-properties.xml", "classpath:dubbo-demo-provider.xml"})
    @DubboComponentScan(basePackages = "me.lucas.kits.rpc.dubbo.provider")
    public static class ProviderConfig{

    }
}

2. 启动

运行1.2.3. 程序入口中的代码,启动Producer

3. 启动分析

3.1. ServiceBean

/**
 * ServiceFactoryBean
 *
 * @export
 */
// ServiceConfig:配置文件属性
// ApplicationContextAware:获取ApplicationContext
// InitializingBean: 初始化时获取配置,将ServiceConfig中的field赋值
// ApplicationListener<ContextRefreshedEvent>:当监听到ContextRefreshedEvent时间时触发服务注册
public class ServiceBean<T> extends ServiceConfig<T> implements InitializingBean, DisposableBean, ApplicationContextAware, ApplicationListener<ContextRefreshedEvent>, BeanNameAware {

ServiceBean是Dubbo服务的工厂,会在初始化时读取(由Spring创建的)配置文件中定义的Bean,将配置文件中配置的属性值添加到配置实体Bean中。
ServiceBean实现ApplicationListener接口,当监听到ContextRefreshedEvent(Spring应用程序上下文初始化或刷新时会触发)事件时调export()方法暴露Dubbo服务

@Override
public void onApplicationEvent(ContextRefreshedEvent event) {
    if (isDelay() && !isExported() && !isUnexported()) {
        if (logger.isInfoEnabled()) {
            logger.info("The service ready on spring started. service: " + getInterface());
        }
        export();
    }
}

public synchronized void export() {
  ···
  doExport();
  ···
}
protected synchronized void doExport() {
  ···
  doExportUrls();
  ProviderModel providerModel = new ProviderModel(getUniqueServiceName(), this, ref);
  ApplicationModel.initProviderModel(getUniqueServiceName(), providerModel);
}
private void doExportUrls() {
    // 经过前面一系列处理之后得到的注册RUL:
    // registry://127.0.0.1:2181/com.alibaba.dubbo.registry.RegistryService?application=demo-provider&client=curator&dubbo=2.6.2&owner=lucas&pid=25827&registry=zookeeper&timestamp=1536302767989
    List<URL> registryURLs = loadRegistries(true);
    for (ProtocolConfig protocolConfig : protocols) {
        // 真正的注册
        doExportUrlsFor1Protocol(protocolConfig, registryURLs);
    }
}
相关实践学习
基于MSE实现微服务的全链路灰度
通过本场景的实验操作,您将了解并实现在线业务的微服务全链路灰度能力。
目录
相关文章
|
1月前
|
Dubbo Cloud Native 网络协议
【Dubbo3技术专题】「服务架构体系」第一章之Dubbo3新特性要点之RPC协议分析介绍
【Dubbo3技术专题】「服务架构体系」第一章之Dubbo3新特性要点之RPC协议分析介绍
51 1
|
1月前
|
存储 负载均衡 监控
深入理解Dubbo-6.服务消费源码分析(下)
深入理解Dubbo-6.服务消费源码分析
73 0
|
1月前
|
缓存 Dubbo Java
深入理解Dubbo-5.服务注册源码分析(下)
深入理解Dubbo-5.服务注册源码分析
45 0
|
1月前
|
缓存 编解码 Dubbo
深入理解Dubbo-5.服务注册源码分析(中)
深入理解Dubbo-5.服务注册源码分析
55 0
|
1月前
|
Dubbo Java 应用服务中间件
深入理解Dubbo-5.服务注册源码分析(上)
深入理解Dubbo-5.服务注册源码分析
66 0
|
7月前
|
负载均衡 Dubbo 应用服务中间件
微服务技术系列教程(31) - Dubbo-原理及负载均衡分析
微服务技术系列教程(31) - Dubbo-原理及负载均衡分析
61 0
|
1月前
|
负载均衡 Dubbo 算法
深入理解Dubbo-2.Dubbo功能之高级特性分析
深入理解Dubbo-2.Dubbo功能之高级特性分析
68 0
|
1月前
|
XML Dubbo Java
【Dubbo3技术专题】回顾Dubbo2.x的技术原理和功能实现及源码分析(温故而知新)(二)
【Dubbo3技术专题】回顾Dubbo2.x的技术原理和功能实现及源码分析(温故而知新)
37 2
|
1月前
|
XML 监控 Dubbo
【Dubbo3技术专题】回顾Dubbo2.x的技术原理和功能实现及源码分析(温故而知新)(一)
【Dubbo3技术专题】回顾Dubbo2.x的技术原理和功能实现及源码分析(温故而知新)
77 1
|
1月前
|
Java fastjson 数据安全/隐私保护
【Dubbo3技术专题】「云原生微服务开发实战」 一同探索和分析研究RPC服务的底层原理和实现
【Dubbo3技术专题】「云原生微服务开发实战」 一同探索和分析研究RPC服务的底层原理和实现
101 0