Dubbo 简记

[TOC]

Spring XML 方式

直连方式

provider

添加一个 provider service:

public interface ProviderService {
    String sayHello(String word);
}

实现该接口:

public class ProviderServiceImpl implements ProviderService {
    @Override
    public String sayHello(String name) {
        return "Hello, " + name;
    }
}

提供 dubbo 配置 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://code.alibabatech.com/schema/dubbo"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd">
    <dubbo:application name="provider" owner="bolitao"/>
    <dubbo:monitor protocol="registry"/>
    <!--暂不使用注册中心-->
    <dubbo:registry address="N/A"/>
    <dubbo:protocol name="dubbo" port="20880"/>
    <dubbo:service interface="xyz.bolitao.service.ProviderService" ref="providerService"/>
    <bean id="providerService" class="xyz.bolitao.service.ProviderServiceImpl"/>
</beans>

编写 main()

public static void main(String[] args) throws IOException {
    ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("provider.xml");
    context.start();
    System.in.read();
}

启动 provider,可以看到 dubbo 已开启服务:

image-20200723112448430

文件树如下:

image-20200723140153404

consumer

添加 provider 依赖,consumer 的其余依赖和 provider 一致:

<dependencies>
    <dependency>
        <groupId>xyz.bolitao</groupId>
        <artifactId>provider</artifactId>
        <version>1.0-SNAPSHOT</version>
    </dependency>
    <!--其他依赖项-->
    ...
</dependencies>

添加 dubbo 配置 consumer.xml,注意调用地址 dubbo://172.16.44.186:20880/xyz.bolitao.service.ProviderService

<?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://code.alibabatech.com/schema/dubbo"
       xsi:schemaLocation="http://www.springframework.org/schema/beans        http://www.springframework.org/schema/beans/spring-beans.xsd        http://code.alibabatech.com/schema/dubbo        http://code.alibabatech.com/schema/dubbo/dubbo.xsd">
    <dubbo:application name="consumer" owner="bolitao"/>
    <dubbo:registry address="N/A"/>
    <dubbo:reference id="providerService" interface="xyz.bolitao.service.ProviderService" url="dubbo://172.16.44.186:20880/xyz.bolitao.service.ProviderService"/>
</beans>

添加 comsumer 的 main() 方法,通过 dubbo 调用 sayHello() 方法:

public static void main(String[] args) throws IOException {
    ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("consumer.xml");
    context.start();
    ProviderService providerService = (ProviderService) context.getBean("providerService");
    String str = providerService.sayHello("dubbo");
    System.out.println(str);
    System.in.read();
}

运行 consumer 后,可以看到以下信息:

image-20200723143155544

代码文件树如下:

image-20200723143231048

Zookeeper 注册中心方式

provider 修改

修改 provider.xml

<!--原始值:-->
<dubbo:registry address="N/A"/>

<!--修改为以下值:-->
<dubbo:registry protocol="zookeeper" address="127.0.0.1:2181" check="false"/>

consumer 修改

与 provider 类似,将 dubbo:registryaddress 值修改为 zk 地址:

<dubbo:registry protocol="zookeeper" address="127.0.0.1:2181" check="false"/>

将 reference 的 URL 删去,consumer 将从 zk 获取服务地址:

<!--原来的 reference 配置:-->
<dubbo:reference id="providerService" interface="xyz.bolitao.service.ProviderService"
                     url="dubbo://172.16.44.186:20880/xyz.bolitao.service.ProviderService"/>

<!--新的 renfence 配置:-->
<dubb:reference interface="xyz.bolitao.service.ProviderService" id="providerService"/>

运行结果

运行 provider:

image-20200723152646070

运行 consumer:

image-20200723154221698

zk 中注册的服务:

image-20200723154938490

Spring 注解配置方式(com.alibaba.dubbo)

provider

ProviderServiceAnnotation 类:

public interface ProviderServiceAnnotation {
    String sayHelloAnnotation(String name);
}

ProviderServiceImplAnnonation 类,使用 dubbo 提供的 @Service 注解进行声明:

@Service(timeout = 5000)
public class ProviderServiceImplAnnonation implements ProviderServiceAnnotation {
    @Override
    public String sayHelloAnnotation(String name) {
        return "Hello, " + name;
    }
}

DubboConfiguration 配置类:

@Configuration
@EnableDubbo(scanBasePackages = "xyz.bolitao.service.annotation")
public class DubboConfiguration {
    @Bean
    public ProviderConfig providerConfig() {
        ProviderConfig providerConfig = new ProviderConfig();
        providerConfig.setTimeout(1000);
        return providerConfig;
    }

    @Bean
    public ApplicationConfig applicationConfig() {
        ApplicationConfig applicationConfig = new ApplicationConfig();
        applicationConfig.setName("dubbo-annotation-provider");
        return applicationConfig;
    }

    @Bean
    public RegistryConfig registryConfig() {
        RegistryConfig registryConfig = new RegistryConfig();
        registryConfig.setProtocol("zookeeper");
        registryConfig.setAddress("localhost");
        registryConfig.setPort(2181);
        return registryConfig;
    }

    @Bean
    public ProtocolConfig protocolConfig() {
        ProtocolConfig protocolConfig = new ProtocolConfig();
        protocolConfig.setName("dubbo");
        protocolConfig.setPort(20880);
        return protocolConfig;
    }
}

运行如下:

image-20200724090003787

代码文件树如下:

image-20200724084635050

consumer

添加 ConsumerAnnotationService,用以替代 XML 形式配置中的 dubb:reference interface

@Component("annotatedConsumer")
public class ConsumerAnnotationService {
    @Reference
    private ProviderServiceAnnotation providerServiceAnnotation;

    public String doSayHello(String content) {
        return providerServiceAnnotation.sayHelloAnnotation(content);
    }
}

添加一个配置类 DubboConsumerConfiguration

@Configuration
@EnableDubbo(scanBasePackages = "xyz.bolitao.consumer.annotation")
@ComponentScan(value = "xyz.bolitao.consumer.annotation")
public class DubboConsumerConfiguration {
    @Bean
    public ApplicationConfig applicationConfig() {
        ApplicationConfig applicationConfig = new ApplicationConfig();
        applicationConfig.setName("dubbo-annotation-consumer");
        Map<String, String> stringStringMap = new HashMap<>(5);
        stringStringMap.put("qos.enable", "true");
        stringStringMap.put("qos.accept.foreign.ip", "true");
        stringStringMap.put("qos.port", "22221");
        applicationConfig.setParameters(stringStringMap);
        return applicationConfig;
    }

    @Bean
    public ConsumerConfig consumerConfig() {
        ConsumerConfig consumerConfig = new ConsumerConfig();
        consumerConfig.setTimeout(3000);
        return consumerConfig;
    }

    @Bean
    public RegistryConfig registryConfig() {
        RegistryConfig registryConfig = new RegistryConfig();
        registryConfig.setProtocol("zookeeper");
        registryConfig.setAddress("localhost");
        registryConfig.setPort(2181);
        return registryConfig;
    }
}

编写 consumer main 方法:

public static void main(String[] args) {
    AnnotationConfigApplicationContext context =
        new AnnotationConfigApplicationContext(DubboConsumerConfiguration.class);
    context.start();
    ConsumerAnnotationService consumerAnnotationService = context.getBean(ConsumerAnnotationService.class);
    System.out.println(consumerAnnotationService.doSayHello("dubbo"));
}

运行结果如下:

image-20200724092500311

目录树如下:

image-20200724094138381

总结:使用 Spring 时,该方法还不如 xml 方式简洁。

Spring Boot 方式(dubbo-spring-boot-starter)

alibaba 的 spring boot starter 已经不维护,apache 继续维护的 starter GitHub 页为:apache/dubbo-spring-boot-project: Spring Boot Project for Apache Dubbo。这里使用 Apache 维护的 starter。

API

建立一个 API model,只写一个接口:

public interface TestService {
    public String doSth(String content);
}

代码目录树如下:

image-20200724135656091

provider

新建一个 starter_provider 模块,添加依赖如下:

<dependency>
    <groupId>xyz.bolitao</groupId>
    <artifactId>api</artifactId><!--该包为上节添加的 api 模块-->
    <version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
    <groupId>org.apache.dubbo</groupId>
    <artifactId>dubbo</artifactId>
    <version>2.7.3</version>
</dependency>
<dependency>
    <groupId>org.apache.zookeeper</groupId>
    <artifactId>zookeeper</artifactId>
    <version>3.6.1</version>
</dependency>
<dependency>
    <groupId>org.apache.curator</groupId>
    <artifactId>curator-framework</artifactId>
    <version>4.2.0</version>
</dependency>
<dependency>
    <groupId>org.apache.curator</groupId>
    <artifactId>curator-recipes</artifactId>
    <version>4.2.0</version>
</dependency>
<dependency>
    <groupId>org.apache.dubbo</groupId>
    <artifactId>dubbo-spring-boot-starter</artifactId>
    <version>2.7.3</version>
</dependency>

修改 springboot 启动配置如下:

server.port=10010
dubbo.application.id=provider
dubbo.application.name=provider
dubbo.registry.address=zookeeper://192.168.200.1:2181
dubbo.provider.threads=10
dubbo.provider.threadpool=fixed
dubbo.provider.loadbalance=roundrobin
dubbo.server=true
dubbo.protocol.name=dubbo
dubbo.protocol.port=20880

之后实现 TestService 接口,注意 @Service 注解不由 spring 提供,而使用 org.apache.dubbo.config.annotation 包:

@Service(version = "1.0.0")
public class TestServiceImpl implements TestService {
    private static final Logger logger = LoggerFactory.getLogger(Application.class);

    @Override
    public String doSth(String content) {
        logger.info("provider 服务被调用");
        return "Hello, " + content;
    }
}

main 方法外,添加 @DubboComponentScan 注解,指定 dubbo 扫描的包位置:

@SpringBootApplication
@DubboComponentScan(basePackages = "xyz.bolitao.starter_provider.service.impl")
public class StarterProviderApplication {
    public static void main(String[] args) {
        ...

代码目录树如下:

image-20200724135630463

consumer

新建 starter-consumer module,创建 module 时勾选 web starter 依赖,并添加刚才自己创建的 api 和 starter_provider 模块:

<dependency>
    <groupId>xyz.bolitao</groupId>
    <artifactId>api</artifactId>
    <version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
    <groupId>xyz.bolitao</groupId>
    <artifactId>starter_provider</artifactId>
    <version>0.0.1-SNAPSHOT</version>
</dependency>
...
<!--还需添加和 provider 一样的 dubbo、zk 相关依赖-->

修改 Spring Boot 应用配置:

server.port=10011
dubbo.application.id=consumer
dubbo.application.name=consumer
dubbo.registry.address=zookeeper://192.168.200.1:2181
dubbo.consumer.check=true

添加一个 REST controller,用于远程调用 provider 的方法:

@RestController
@RequestMapping("test")
public class TestController {
    @Reference(version = "1.0.0")
    private TestService testService;

    @GetMapping("{content}")
    public String test(@PathVariable String content) {
        return testService.doSth(content);
    }
}

代码文件树如下:

image-20200724140048116

运行效果

依次运行 provider 和 consumer,访问 consumer 提供的 127.0.0.1:10011/test/{content} 页面:

image-20200724140239023

provider 控制台有以下内容输出:

image-20200724140410967

加载评论