Dubbo源码分析1:生产者启动分析-阿里云开发者社区

开发者社区> 开发与运维> 正文

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

简介: 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);
    }
}

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

分享:
开发与运维
使用钉钉扫一扫加入圈子
+ 订阅

集结各类场景实战经验,助你开发运维畅行无忧

其他文章