2. 架构设计
Dubbo 定义了以下核心角色:
- Provider - 服务提供方,负责暴露服务并注册到注册中心
- Container - 服务容器,负责启动、加载和运行服务
- Consumer - 服务消费方,通过注册中心订阅所需服务
- Registry - 注册中心,用于服务注册与发现
- Monitor - 监控中心,记录服务调用统计信息(如指定时间内的调用频率)
(来源: http://dubbo.io/images/dubbo-architecture.png)
✅ Provider、Consumer 和 Registry 之间保持长连接,当服务提供者宕机时,注册中心能立即感知并通知消费者 ⚠️ Registry 和 Monitor 是可选组件,消费者可直接连接提供者,但会影响系统稳定性
3. Maven 依赖
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo</artifactId>
<version>2.5.7</version>
</dependency>
最新版本可查阅 Maven 中央仓库
4. 快速上手
4.1. 多播注册中心 - 服务提供者
public interface GreetingsService {
String sayHi(String name);
}
public class GreetingsServiceImpl implements GreetingsService {
@Override
public String sayHi(String name) {
return "hi, " + name;
}
}
💡 消费者和提供者必须共享接口定义,这是实现远程调用的基础
4.2. 多播注册中心 - 服务注册
<dubbo:application name="demo-provider" version="1.0"/>
<dubbo:registry address="multicast://224.1.1.1:9090"/>
<dubbo:protocol name="dubbo" port="20880"/>
<bean id="greetingsService" class="com.baeldung.dubbo.remote.GreetingsServiceImpl"/>
<dubbo:service interface="com.baeldung.dubbo.remote.GreetingsService"
ref="greetingsService"/>
通过此配置,服务将暴露在
dubbo://127.0.0.1:20880
并注册到多播地址
<dubbo:application>
定义应用元数据<dubbo:protocol>
指定通信协议(默认基于 NIO)<dubbo:service>
声明要发布的服务接口
4.3. 多播注册中心 - 服务消费者
<dubbo:application name="demo-consumer" version="1.0"/>
<dubbo:registry address="multicast://224.1.1.1:9090"/>
<dubbo:reference interface="com.baeldung.dubbo.remote.GreetingsService"
id="greetingsService"/>
验证代码:
public class MulticastRegistryTest {
@Before
public void initRemote() {
ClassPathXmlApplicationContext remoteContext
= new ClassPathXmlApplicationContext("multicast/provider-app.xml");
remoteContext.start();
}
@Test
public void givenProvider_whenConsumerSaysHi_thenGotResponse(){
ClassPathXmlApplicationContext localContext
= new ClassPathXmlApplicationContext("multicast/consumer-app.xml");
localContext.start();
GreetingsService greetingsService
= (GreetingsService) localContext.getBean("greetingsService");
String hiMessage = greetingsService.sayHi("baeldung");
assertNotNull(hiMessage);
assertEquals("hi, baeldung", hiMessage);
}
}
🔍 消费者通过代理透明调用远程服务,无需感知底层实现 ❌ 直连方式(不推荐):
url="dubbo://127.0.0.1:20880"
4.4. 简单注册中心
<dubbo:application name="simple-registry" />
<dubbo:protocol port="9090" />
<dubbo:service interface="com.alibaba.dubbo.registry.RegistryService"
ref="registryService" registry="N/A" ondisconnect="disconnect">
<dubbo:method name="subscribe">
<dubbo:argument index="1" callback="true" />
</dubbo:method>
<dubbo:method name="unsubscribe">
<dubbo:argument index="1" callback="true" />
</dubbo:method>
</dubbo:service>
<bean class="com.alibaba.dubbo.registry.simple.SimpleRegistryService"
id="registryService" />
⚠️ 需从 GitHub 复制源码 ✅ 仅适用于测试环境,生产环境请勿使用
4.5. Java 配置方式
服务提供者配置:
ApplicationConfig application = new ApplicationConfig();
application.setName("demo-provider");
application.setVersion("1.0");
RegistryConfig registryConfig = new RegistryConfig();
registryConfig.setAddress("multicast://224.1.1.1:9090");
ServiceConfig<GreetingsService> service = new ServiceConfig<>();
service.setApplication(application);
service.setRegistry(registryConfig);
service.setInterface(GreetingsService.class);
service.setRef(new GreetingsServiceImpl());
service.export();
服务消费者配置:
ApplicationConfig application = new ApplicationConfig();
application.setName("demo-consumer");
application.setVersion("1.0");
RegistryConfig registryConfig = new RegistryConfig();
registryConfig.setAddress("multicast://224.1.1.1:9090");
ReferenceConfig<GreetingsService> reference = new ReferenceConfig<>();
reference.setApplication(application);
reference.setRegistry(registryConfig);
reference.setInterface(GreetingsService.class);
GreetingsService greetingsService = reference.get();
String hiMessage = greetingsService.sayHi("baeldung");
💡 复杂场景建议优先使用 XML 配置,功能更完整
5. 协议支持
Dubbo 支持多种协议:
- dubbo(默认)
- RMI
- Hessian
- HTTP
- Web Service
- Thrift
- Memcached
- Redis
Dubbo 协议特点:
- 保持长连接(NIO 非阻塞)
- 小数据包(<100K)传输性能优异
<dubbo:protocol name="dubbo" port="20880" connections="2" accepts="1000" />
多协议暴露示例:
<dubbo:protocol name="dubbo" port="20880" />
<dubbo:protocol name="rmi" port="1099" />
<dubbo:service interface="com.baeldung.dubbo.remote.GreetingsService"
version="1.0.0" ref="greetingsService" protocol="dubbo" />
<dubbo:service interface="com.bealdung.dubbo.remote.AnotherService"
version="1.0.0" ref="anotherService" protocol="rmi" />
6. 结果缓存
<dubbo:reference interface="com.baeldung.dubbo.remote.GreetingsService"
id="greetingsService" cache="lru" />
✅ 支持 LRU、线程本地缓存和 JCache
缓存验证代码:
public class GreetingsServiceSpecialImpl implements GreetingsService {
@Override
public String sayHi(String name) {
try {
SECONDS.sleep(5); // 模拟耗时操作
} catch (Exception ignored) { }
return "hi, " + name;
}
}
@Test
public void givenProvider_whenConsumerSaysHi_thenGotResponse() {
// ... 初始化上下文
GreetingsService greetingsService = (GreetingsService) localContext.getBean("greetingsService");
long before = System.currentTimeMillis();
String hiMessage = greetingsService.sayHi("baeldung");
long timeElapsed = System.currentTimeMillis() - before;
assertTrue(timeElapsed > 5000); // 首次调用 >5秒
before = System.currentTimeMillis();
hiMessage = greetingsService.sayHi("baeldung");
timeElapsed = System.currentTimeMillis() - before;
assertTrue(timeElapsed < 1000); // 缓存命中 <1秒
}
7. 集群支持
7.1. 负载均衡
注册中心配置:
<dubbo:registry address="zookeeper://127.0.0.1:2181"/>
需添加依赖:
<dependency> <groupId>org.apache.zookeeper</groupId> <artifactId>zookeeper</artifactId> <version>3.4.11</version> </dependency> <dependency> <groupId>com.101tec</groupId> <artifactId>zkclient</artifactId> <version>0.10</version> </dependency>
负载均衡策略:
- random(随机)
- roundrobin(轮询)
- leastactive(最少活跃)
- consistenthash(一致性哈希)
消费者配置:
<dubbo:reference interface="com.baeldung.dubbo.remote.GreetingsService"
id="greetingsService" loadbalance="roundrobin" />
动态负载均衡验证:
@Test
public void givenProviderCluster_whenConsumerSaysHi_thenResponseBalanced() {
// ... 初始化上下文
GreetingsService greetingsService = (GreetingsService) localContext.getBean("greetingsService");
List<Long> elapseList = new ArrayList<>(6);
for (int i = 0; i < 6; i++) {
long current = System.currentTimeMillis();
greetingsService.sayHi("baeldung");
elapseList.add(System.currentTimeMillis() - current);
}
OptionalDouble avgElapse = elapseList.stream().mapToLong(e -> e).average();
assertTrue(avgElapse.getAsDouble() > 2500.0); // 平均耗时 >2.5秒
}
💡 集群包含快速响应提供者(0秒)和慢速提供者(5秒),轮询策略下平均耗时应为 (0+5)/2=2.5秒
7.2. 容错策略
支持策略:
- failover(失败自动切换)
- failsafe(失败安全)
- failfast(快速失败)
- failback(失败重试)
- forking(并行调用)
容错配置示例:
<dubbo:service interface="com.baeldung.dubbo.remote.GreetingsService"
ref="greetingsService" cluster="failover"/>
失败重试验证:
public class GreetingsFailoverServiceImpl implements GreetingsService {
@Override
public String sayHi(String name) {
return "hi, failover " + name;
}
}
// 消费者配置:retries="2" timeout="2000"
@Test
public void whenConsumerSaysHi_thenGotFailoverResponse() {
// ... 初始化上下文
GreetingsService greetingsService = (GreetingsService) localContext.getBean("greetingsService");
String hiMessage = greetingsService.sayHi("baeldung");
assertEquals("hi, failover baeldung", hiMessage); // 超时后切换到备用服务
}
8. 总结
Dubbo 作为阿里巴巴开源的 RPC 框架,其核心优势在于:
- ✅ 简洁易用的服务治理能力
- ✅ 支持平滑重构单体应用到分布式架构
- ✅ 丰富的扩展特性(多协议、集群、缓存等)
💡 本文仅介绍基础功能,更多高级特性如参数校验、回调通知、泛化调用等待探索。完整示例代码请参考 GitHub 仓库。