个人学习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配置覆盖]遵循以下逻辑:
- 优先使用JVM参数
- 其次使用XML配置
- 最后使用配置文件配置
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®istry=zookeeper×tamp=1536302767989
List<URL> registryURLs = loadRegistries(true);
for (ProtocolConfig protocolConfig : protocols) {
// 真正的注册
doExportUrlsFor1Protocol(protocolConfig, registryURLs);
}
}