4 - Dubbo x Spring XML 开发微服务应用

本文将演示如何基于 Dubbo Samples,通过 Dubbo x Spring XML 快速开发微服务应用。

目标

从零开始开发 Dubbo x Spring XML 基于的微服务开发,并理解 Dubbo x Spring XML 的配置方式。

难度

环境要求

  • 系统:Windows、Linux、MacOS

  • JDK 8 及以上(推荐 JDK17)

  • Git

  • IntelliJ IDEA(可选)

  • Docker(可选)

快速部署(直接基于 Samples 启动)

本章将手把手教你通过几个简单的命令,部署并运行一个基于 Dubbo x Spring XML 的用例。

注意:本章部署的代码细节可以在 apache/dubbo-samples 仓库的 1-basic/dubbo-samples-spring-xml 中找到,下一章也会进行讲解。

1. 获取测试项目

在开始整个教程之前,我们需要获取测试项目的代码。Dubbo 的所有测试用例代码都存储在 apache/dubbo-samples 仓库中,以下命令可以帮助你获取 Samples 仓库中的所有代码。

git clone --depth=1 --branch master git@github.com:apache/dubbo-samples.git

2. 启动一个简单的注册中心

对于一个微服务应用来说,注册中心是一个不可或缺的组件。只有通过注册中心,消费者才能成功发现服务端的地址信息,进而进行调用。

为了让本教程更易于使用,我们提供了一个基于 Apache Zookeeper 注册中心的简单启动器。如果你需要在生产环境中部署注册中心,请参考 生产环境初始化 部署高可用的注册中心。

Windows:
./mvnw.cmd clean compile exec:java -pl tools/embedded-zookeeper

Linux / MacOS:
./mvnw clean compile exec:java -pl tools/embedded-zookeeper

Docker:
docker run --name some-zookeeper -p 2181:2181 --restart always -d zookeeper

3. 启动服务提供者

启动注册中心后,下一步就是启动一个对外提供服务的服务提供者。dubbo-samples 中也提供了相应的示例,可以通过以下命令快速拉起。

Windows:
./mvnw.cmd clean compile exec:java -pl 1-basic/dubbo-samples-spring-xml "-Dexec.mainClass=org.apache.dubbo.samples.provider.Application"

Linux / MacOS:
./mvnw clean compile exec:java -pl 1-basic/dubbo-samples-spring-xml -Dexec.mainClass="org.apache.dubbo.samples.provider.Application"

Note: You need to open an independent terminal to run, and the command will keep executing.

执行完以上命令后,等待片刻,直到出现以下日志(Dubbo Application[1.1](demo-provider) is ready.),就表示服务提供者已经启动,说明服务提供者可以提供服务了。

[08/02/23 03:26:52:052 CST] org.apache.dubbo.samples.provider.Application.main() INFO metadata.ConfigurableMetadataServiceExporter: [DUBBO] The MetadataService exports urls : [dubbo://30.221. 128.96:20880/org.apache.dubbo.metadata.MetadataService?anyhost=true&application=demo-provider&background=false&bind.ip=30.221.128.96&bind.port=20880&connections=1&corethreads=2&delay=true0&deprecated=false&dubbo=10ync=0genic=0genic=0&exeted =false&getAndListenInstanceMetadata.1.callback=true&getAndListenInstanceMetadata.return=true&getAndListenInstanceMetadata.sent=true&group=demo-provider&interface=org.apache.dubbo.metadata.MetadataService&ipv6=fd00:1:5:5200:4d53:9f5:a545:804d&methods=exportInstanceMetadata,getAndListenInstanceMetadata , getExportedServiceURLs, getExportedURLs, getExportedURLs, getExportedURLs, getExportedURLs, getExportedURLs, getInstanceMetadataChangedListenerMap, getMetadataInfo, getMetadataInfos, getMetadataURL, getServiceDefinition, getServiceDefinition, getSubscribedURLs, isMetadata aService,serviceName,toSortedStrings,toSortedStrings,version&pid=70803&register=false&release=3.1.6&revision=3.1.6&side=provider&threadpool=cached&threads=100&timestamp=1675841212727&version=1.0.0], dubbo version: 3.1.23host: 6
[08/02/23 03:26:52:052 CST] org.apache.dubbo.samples.provider.Application.main() INFO metadata.ServiceInstanceMetadataUtils: [DUBBO] Start registering instance address to registry., dubbo version: 3.1 .6, current host: 30.221.128.96
[08/02/23 03:26:52:052 CST] org.apache.dubbo.samples.provider.Application.main() INFO metadata.MetadataInfo: [DUBBO] metadata revision changed: null -> 602d44cc6d653b9cd42ab23c3948b5ab, app: demo -provider, services: 1, dubbo version: 3.1.6, current host: 30.221.128.96
[08/02/23 03:26:52:052 CST] org.apache.dubbo.samples.provider.Application.main() INFO deploy.DefaultApplicationDeployer: [DUBBO] Dubbo Application[1.1](demo-provider) is ready ., dubbo version: 3.1.6, current host: 30.221.128.96

4. 启动服务消费者

最后一步是启动一个服务消费者来调用服务提供者,这是 RPC 调用的核心,为服务消费者调用服务提供者提供桥梁。

Windows:
./mvnw.cmd clean compile exec:java -pl 1-basic/dubbo-samples-spring-xml "-Dexec.mainClass=org.apache.dubbo.samples.client.Application"

Linux / MacOS:
./mvnw clean compile exec:java -pl 1-basic/dubbo-samples-spring-xml -Dexec.mainClass="org.apache.dubbo.samples.client.Application"

执行完以上命令后,等待片刻,直到出现以下日志(hi, dubbo),打印的数据是服务提供者处理后返回的,标志着一次服务调用成功。

[08/02/23 03:28:23:023 CST] org.apache.dubbo.samples.client.Application.main() INFO deploy.DefaultApplicationDeployer: [DUBBO] Dubbo Application[1.1](demo-consumer) is ready ., dubbo version: 3.1.6, current host: 30.221.128.96
Receive result ======> hi, dubbo

动手实践(从零代码开发版本)

本章将手把手教你通过一步步的教程,从零开始开发一个微服务应用。

1. 启动注册中心

对于一个微服务应用来说,注册中心是一个不可或缺的组件。只有通过注册中心,消费者才能成功发现服务端的地址信息,进而进行调用。

为了让本教程更易于使用,我们提供了一个基于 Apache Zookeeper 注册中心的简单启动器。如果你需要在生产环境中部署注册中心,请参考 生产环境初始化 部署高可用的注册中心。

Windows:
git clone --depth=1 --branch master git@github.com:apache/dubbo-samples.git
cd dubbo-samples
./mvnw.cmd clean compile exec:java -pl tools/embedded-zookeeper

Linux / MacOS:
git clone --depth=1 --branch master git@github.com:apache/dubbo-samples.git
cd dubbo-samples
./mvnw clean compile exec:java -pl tools/embedded-zookeeper

Docker:
docker run --name some-zookeeper -p 2181:2181 --restart always -d zookeeper

2. 初始化项目

从本节开始,项目将基于 IntelliJ IDEA 进行构建和测试。

img

如上图所示,可以构建一个基本的项目。

img

初始化项目后,需要在 src/main/java 目录下创建 org.apache.dubbo.samples.apiorg.apache.dubbo.samples.clientorg.apache.dubbo.samples.provider 三个包。

未来,我们将在 api 下创建对应的接口,在 client 下创建对应的客户端订阅服务功能,在 provider 下创建对应的服务端实现和发布服务功能。

以上三个包分别对应应用依赖的 API、消费者端应用的模块和服务端应用的模块。在实际部署中,需要拆分成三个项目,消费者和服务的共同依赖是 api 模块。从简易性出发,本教程将开发在同一个项目中,通过多个启动类进行区分。

3. 添加 Maven 依赖

初始化项目后,我们需要先添加 Dubbo 相关的 maven 依赖。

img

编辑 pom.xml 文件,添加以下配置。

    <dependencies>
        <dependency>
            <groupId>org.apache.dubbo</groupId>
            <artifactId>dubbo</artifactId>
            <version>3.1.6</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.3.25</version>
        </dependency>

        <dependency>
            <groupId>org.apache.curator</groupId>
            <artifactId>curator-x-discovery</artifactId>
            <version>5.2.0</version>
        </dependency>
        <dependency>
            <groupId>org.apache.zookeeper</groupId>
            <artifactId>zookeeper</artifactId>
            <version>3.8.0</version>
        </dependency>
    </dependencies>

在这个配置中,定义了 dubbo 和 zookeeper(以及对应的连接器 curator)的依赖。

img

添加完以上配置后,可以通过 IDEA 的 Maven - Reload All Maven Projects 刷新依赖。

4. 定义服务接口

服务接口是 Dubbo 中消费者和服务端之间的桥梁。

img

org.apache.dubbo.samples.api 下创建 GreetingsService 接口,定义如下

package org.apache.dubbo.samples.api;

public interface GreetingsService {

    String sayHi(String name);
}

GreetingsService 中,定义了 sayHi 方法。后续服务端发布的服务和消费者订阅的服务,都是围绕 GreetingsService 接口进行开发的。

5. 定义服务端的实现

定义完服务接口后,就可以在服务端定义对应的实现。与消费者端相比,这部分的实现是远程实现,本地没有相关信息。

img

org.apache.dubbo.samples.provider 包下创建 GreetingsServiceImpl 类,定义如下

package org.apache.dubbo.samples.provider;

import org.apache.dubbo.samples.api.GreetingsService;

public class GreetingsServiceImpl implements GreetingsService {
    @Override
    public String sayHi(String name) {
        return "hi," + name;
    }
}

GreetingsServiceImpl 中,实现 GreetingsService 接口,对于 sayHi 方法,返回 hi, name

6. 配置服务端 XML 配置文件

从这一步到第 7 步,Dubbo 服务的信息将通过 Spring XML 配置。

首先,让我们为服务器创建一个配置文件。

img

resources 资源文件夹下创建一个 dubbo-demo-provider.xml 文件,定义如下

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

    <!-- Define application name -->
    <dubbo:application name="demo-provider"/>

    <!-- Define the registration center address -->
    <dubbo:registry address="zookeeper://127.0.0.1:2181"/>

    <!-- Define the bean corresponding to the implementation class -->
    <bean id="greetingsService" class="org.apache.dubbo.samples.provider.GreetingsServiceImpl"/>
    <!-- Define service information, refer to the above bean -->
    <dubbo:service interface="org.apache.dubbo.samples.api.GreetingsService" ref="greetingsService"/>

</beans>

在这个配置文件中,定义了 Dubbo 的应用程序名称、Dubbo 使用的注册中心地址、发布服务的 Spring bean 以及通过 Dubbo 发布的 bean。

7. 配置消费者 XML 配置文件

同样地,我们需要为消费者创建一个配置文件。

img

resources 资源文件夹下创建一个 dubbo-demo-consumer.xml 文件,定义如下

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:dubbo="https://dubbo.apache.org/schema/dubbo"
       xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
       https://dubbo.apache.org/schema/dubbo https://dubbo.apache.org/schema/dubbo/dubbo.xsd http://www.springframework.org/schema/context http://www.springframework .org/schema/context/spring-context.xsd">
    <context:property-placeholder/>

    <!-- Define application name -->
    <dubbo:application name="demo-provider"/>

    <!-- Define the registration center address -->
    <dubbo:registry address="zookeeper://127.0.0.1:2181"/>

    <!-- Define subscription information, Dubbo will create corresponding beans in Spring Context -->
    <dubbo:reference id="greetingsService" interface="org.apache.dubbo.samples.api.GreetingsService"/>

</beans>

在这个配置文件中,定义了 Dubbo 应用程序名称、Dubbo 使用的注册中心地址以及订阅的服务信息。

8. 基于 Spring 配置服务器启动类

除了配置 XML 配置文件,我们还需要创建一个基于 Spring Context 的启动类。

首先,我们先创建服务器的启动类。

img

org.apache.dubbo.samples.provider 包下创建 Application 类,定义如下

package org.apache.dubbo.samples.provider;

import java.util.concurrent.CountDownLatch;

import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Application {

    public static void main(String[] args) throws InterruptedException {
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("dubbo-demo-provider.xml");
        context. start();

        // Suspend the main thread to prevent exit
        new CountDownLatch(1). await();
    }
}

在这个启动类中,配置了一个 ClassPathXmlApplicationContext 来读取之前步骤 6 中定义的 dubbo-demo-provider.xml 配置文件。

9. 基于 Spring 配置消费者启动类

同样地,我们需要为消费者创建一个启动类。

img

org.apache.dubbo.samples.client 包下创建 Application 类,定义如下

package org.apache.dubbo.samples.client;

import java.io.IOException;

import org.apache.dubbo.samples.api.GreetingsService;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Application {
    public static void main(String[] args) throws IOException {
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("dubbo-demo-consumer.xml");
        context. start();
        GreetingsService greetingsService = (GreetingsService) context. getBean("greetingsService");

        String message = greetingsService.sayHi("dubbo");
        System.out.println("Receive result ======> " + message);
        System.in.read();
        System. exit(0);
    }

}

在这个启动类中,主要执行三个功能

  1. 配置一个 ClassPathXmlApplicationContext 来读取之前步骤 7 中定义的 dubbo-demo-consumer.xml 配置文件

  2. 从 Spring Context 中获取 Dubbo 创建的名为 greetingsService 的 bean

  3. 通过这个 bean 发起对远程端的调用

10. 启动应用程序

到第 9 步,代码已经开发完成,本节将启动整个项目并进行验证。

img

首先启动 org.apache.dubbo.samples.provider.Application,等待一段时间后出现如下所示的日志(Dubbo Application[1.1](demo-provider) is ready),表示服务提供者已启动,表明服务提供者可以对外提供服务。

[DUBBO] Dubbo Application[1.1](demo-provider) is ready., dubbo version: 3.1.6, current host: 30.221.128.96

然后启动 org.apache.dubbo.samples.client.Application,等待一段时间后看到如下所示的日志(hi, dubbo),表示服务消费者已启动,成功获取了对服务器的调用。

img

Receive result ======> hi, dubbo

进一步阅读

1. Dubbo XML 配置介绍

Dubbo 的主要配置项包括 dubbo:applicationdubbo:registrydubbo:referencedubbo:service 等,更多详情请参考 [XML 配置 | Apache Dubbo](/zh-cn/docs3- v2/java-sdk/reference-manual/config/xml/) 文章。

更多

本教程介绍了如何基于 Dubbo x Spring XML 开发微服务应用程序。到目前为止,已经介绍了基于 API、Spring Boot 和 Spring XML 的 Dubbo 三种主要的启动方式。

在下一节中,将介绍基于 Protobuf IDL 配置的微服务开发方法。


最后修改时间:2024 年 4 月 10 日:修复涉及 -Dexec 的 Windows 命令 (#2957) (bbb9a203c3b)