Apache Dubbo 快速入门与集成示例
以直连模式演示 Apache Dubbo 3.2.20 快速上手全流程:环境准备、接口编程、provider 与 consumer 首例及运行解读,并给出 Spring Boot 集成样例与直连、注册中心两种服务发现方式对比。
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/A | registry.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)引用,地址由注册中心下发;集群容错、负载均衡、超时重试等参数与直连模式一致。