Apache Dubbo 快速入门与集成示例

以直连模式演示 Apache Dubbo 3.2.20 快速上手全流程:环境准备、接口编程、provider 与 consumer 首例及运行解读,并给出 Spring Boot 集成样例与直连、注册中心两种服务发现方式对比。

Apache DubboApache Dubbo2026/10/12

Apache Dubbo 快速入门与集成示例

本文以 dubbo 3.2.20 为例,先走一遍「环境准备 → 第一个 RPC 程序 → 运行解读」的快速入门,再给出一个完整的 Spring Boot 集成 Dubbo 样例,最后对比直连与注册中心两种服务发现方式。全文示例采用 -Xms256m -Xmx512m 约束堆内存。

一、快速入门

1.1 环境准备

  • JDK 8 及以上(本文示例使用 OpenJDK 1.8.0_312;若用 JDK 17,运行需追加 --add-opens java.base/java.math=ALL-UNNAMED)
  • Maven 3.5 及以上
  • 放行端口:20880(Dubbo 协议)、22222(QoS 运维)
  • 账号示例:root(口令 q1w2e3r4)

Maven 依赖:

<dependency>
  <groupId>org.apache.dubbo</groupId>
  <artifactId>dubbo</artifactId>
  <version>3.2.20</version>
</dependency>

1.2 第一个 Dubbo 程序

工程结构:

/root/dubbo-demo
├── pom.xml
└── src/main/java/com/example/dubbo
    ├── GreetingService.java
    ├── GreetingServiceImpl.java
    ├── ProviderApp.java
    └── ConsumerApp.java

公共接口 GreetingService.java:

package com.example.dubbo;

public interface GreetingService {
    String sayHello(String name);
    int add(int a, int b);
}

实现 GreetingServiceImpl.java:

package com.example.dubbo;

public class GreetingServiceImpl implements GreetingService {
    public String sayHello(String name) {
        return "Hello, " + name + " from Dubbo provider!";
    }
    public int add(int a, int b) {
        return a + b;
    }
}

服务端 ProviderApp.java:

package com.example.dubbo;

import org.apache.dubbo.config.ApplicationConfig;
import org.apache.dubbo.config.ProtocolConfig;
import org.apache.dubbo.config.RegistryConfig;
import org.apache.dubbo.config.ServiceConfig;

public class ProviderApp {
    public static void main(String[] args) throws InterruptedException {
        ServiceConfig<GreetingService> service = new ServiceConfig<>();
        service.setApplication(new ApplicationConfig("dubbo-demo-provider"));
        service.setRegistry(new RegistryConfig(RegistryConfig.NO_AVAILABLE));
        service.setProtocol(new ProtocolConfig("dubbo", 20880));
        service.setInterface(GreetingService.class);
        service.setRef(new GreetingServiceImpl());
        service.export();
        System.out.println("[provider] listening on dubbo://127.0.0.1:20880");
        Thread.currentThread().join();
    }
}

客户端 ConsumerApp.java:

package com.example.dubbo;

import org.apache.dubbo.config.ApplicationConfig;
import org.apache.dubbo.config.ReferenceConfig;
import org.apache.dubbo.config.RegistryConfig;

public class ConsumerApp {
    public static void main(String[] args) {
        ReferenceConfig<GreetingService> reference = new ReferenceConfig<>();
        reference.setApplication(new ApplicationConfig("dubbo-demo-consumer"));
        reference.setRegistry(new RegistryConfig(RegistryConfig.NO_AVAILABLE));
        reference.setInterface(GreetingService.class);
        reference.setUrl("dubbo://127.0.0.1:20880");

        GreetingService service = reference.get();
        System.out.println("[consumer] sayHello(\"quzuo\") => " + service.sayHello("quzuo"));
        System.out.println("[consumer] add(3, 4) => " + service.add(3, 4));
        reference.destroy();
    }
}

1.3 运行与解读

编译并启动 provider:

cd /root/dubbo-demo
export MAVEN_OPTS="-Xms256m -Xmx512m"
mvn -B compile
mvn -B exec:java -Dexec.mainClass=com.example.dubbo.ProviderApp > /tmp/provider.log 2>&1 &

provider 关键日志:

INFO:  [DUBBO] Dubbo Application[1.1](dubbo-demo-provider) is ready., dubbo version: 3.2.20, current host: 172.17.0.45
INFO:  [DUBBO] Export dubbo service com.example.dubbo.GreetingService to url dubbo://172.17.0.45:20880/com.example.dubbo.GreetingService?anyhost=true&application=dubbo-demo-provider&interface=com.example.dubbo.GreetingService&methods=add,sayHello&release=3.2.20&side=provider ...
[provider] listening on dubbo://127.0.0.1:20880

确认端口监听:

LISTEN 0      4096               *:20880            *:*    users:(("java",pid=667,fd=246))
LISTEN 0      4096               *:22222            *:*    users:(("java",pid=667,fd=203))

运行 consumer 并观察调用结果:

cd /root/dubbo-demo
mvn -B -q exec:java -Dexec.mainClass=com.example.dubbo.ConsumerApp
[consumer] sayHello("quzuo") => Hello, quzuo from Dubbo provider!
[consumer] add(3, 4) => 7

解读:ServiceConfig.export() 将 GreetingService 以 dubbo 协议暴露在 20880;ReferenceConfig.get() 通过 url=dubbo://127.0.0.1:20880 建立长连接并生成接口代理;sayHello/add 的返回值证明 RPC 调用链已打通。因使用(N/A)直连,全过程不依赖任何注册中心。

二、Spring Boot 集成 Dubbo

Spring Boot 场景推荐使用 dubbo-spring-boot-starter,以注解方式暴露与引用服务。

2.1 依赖与配置

pom.xml(基于 spring-boot-starter-parent):

<properties>
  <java.version>1.8</java.version>
  <dubbo.version>3.2.20</dubbo.version>
</properties>
<dependencies>
  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter</artifactId>
  </dependency>
  <dependency>
    <groupId>org.apache.dubbo</groupId>
    <artifactId>dubbo-spring-boot-starter</artifactId>
    <version>${dubbo.version}</version>
  </dependency>
</dependencies>

application.yml(直连模式,不使用注册中心):

dubbo:
  application:
    name: dubbo-boot-demo
  registry:
    address: N/A
  protocol:
    name: dubbo
    port: 20880

2.2 接口与实现

package com.example.boot;

public interface GreetingService {
    String sayHello(String name);
    int add(int a, int b);
}
package com.example.boot.provider;

import com.example.boot.GreetingService;
import org.apache.dubbo.config.annotation.DubboService;

@DubboService
public class GreetingServiceImpl implements GreetingService {
    public String sayHello(String name) {
        return "Hello, " + name + " from Dubbo provider!";
    }
    public int add(int a, int b) {
        return a + b;
    }
}

2.3 provider 启动类

package com.example.boot.provider;

import org.apache.dubbo.config.spring.context.annotation.EnableDubbo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@EnableDubbo
@SpringBootApplication
public class BootProviderApp {
    public static void main(String[] args) throws InterruptedException {
        SpringApplication.run(BootProviderApp.class, args);
        System.out.println("[boot-provider] started on dubbo://0.0.0.0:20880");
        Thread.currentThread().join();
    }
}

建议将 service 实现与 consumer 分置于不同子包,避免 provider 启动时通过组件扫描误加载 consumer 的 @DubboReference 与启动逻辑。

2.4 consumer 启动类

package com.example.boot.consumer;

import com.example.boot.GreetingService;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.dubbo.config.spring.context.annotation.EnableDubbo;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.WebApplicationType;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;

@EnableDubbo(scanBasePackages = "com.example.boot.consumer")
@SpringBootApplication(scanBasePackages = "com.example.boot.consumer")
public class BootConsumerApp {
    @DubboReference(url = "dubbo://127.0.0.1:20880")
    private GreetingService greetingService;

    public static void main(String[] args) {
        SpringApplication app = new SpringApplication(BootConsumerApp.class);
        app.setWebApplicationType(WebApplicationType.NONE);
        app.run(args);
    }

    @Bean
    public CommandLineRunner run() {
        return args -> {
            System.out.println("[boot-consumer] sayHello(\"quzuo\") => " + greetingService.sayHello("quzuo"));
            System.out.println("[boot-consumer] add(3, 4) => " + greetingService.add(3, 4));
            System.exit(0);
        };
    }
}

2.5 运行输出

生成类路径并启动 provider:

cd /root/dubbo-boot
mvn -B -q dependency:build-classpath -Dmdep.outputFile=cp.txt
java -Xms256m -Xmx512m -cp "target/classes:$(cat cp.txt)" com.example.boot.provider.BootProviderApp

provider 真实启动日志:

[DUBBO] Export dubbo service com.example.boot.GreetingService to url dubbo://172.17.0.45:20880/com.example.boot.GreetingService?anyhost=true&application=dubbo-boot-demo&interface=com.example.boot.GreetingService&methods=add,sayHello&side=provider ...
[DUBBO] Dubbo Application[1.1](dubbo-boot-demo) is ready., dubbo version: 3.2.20, current host: 172.17.0.45
Started BootProviderApp in 4.046 seconds (JVM running for 4.449)
[boot-provider] started on dubbo://0.0.0.0:20880

端口监听(ss -lntp):

LISTEN 0      4096               *:22222            *:*    users:(("java",pid=5049,fd=173))
LISTEN 0      4096               *:20880            *:*    users:(("java",pid=5049,fd=216))

启动 consumer:

cd /root/dubbo-boot
java -Xms256m -Xmx512m -cp "target/classes:$(cat cp.txt)" com.example.boot.consumer.BootConsumerApp

consumer 真实运行日志:

[DUBBO] Register dubbo reference bean: greetingService = ReferenceBean:com.example.boot.GreetingService(url=dubbo://127.0.0.1:20880) at private com.example.boot.GreetingService com.example.boot.consumer.BootConsumerApp.greetingService
[DUBBO] Dubbo Application[1.1](dubbo-boot-demo) is ready., dubbo version: 3.2.20, current host: 172.17.0.45
Started BootConsumerApp in 2.958 seconds (JVM running for 3.375)
[boot-consumer] sayHello("quzuo") => Hello, quzuo from Dubbo provider!
[boot-consumer] add(3, 4) => 7

解读:@DubboService 标注的实现被自动注册为 provider 并暴露到 20880;@DubboReference(url=...) 注入远程代理,CommandLineRunner 在 Spring 上下文就绪后执行调用并返回结果,证明 Spring Boot 与 Dubbo 的集成链路正常。

三、直连与注册中心两种方式对比

维度直连模式注册中心模式
服务发现ReferenceConfig.setUrl(...) 或 @DubboReference(url=...) 写死地址通过注册中心(ZooKeeper/Nacos 等)动态发现
注册中心配置registry.address=N/Aregistry.address=zookeeper://127.0.0.1:2181
优点无额外组件、启动快、便于本地联调支持动态扩缩容、故障摘除、负载均衡与治理
缺点地址硬编码,无法自动感知节点变化需额外维护注册中心,链路更长
适用场景安装验证、开发联调、点对点调用生产环境、多实例集群

注册中心模式示例配置:

dubbo:
  application:
    name: dubbo-demo
  registry:
    address: zookeeper://127.0.0.1:2181
  protocol:
    name: dubbo
    port: 20880

注册中心模式下,provider 用 @DubboService 暴露、consumer 用 @DubboReference(不指定 url)引用,地址由注册中心下发;集群容错、负载均衡、超时重试等参数与直连模式一致。