单元1 · Dubbo 快速入门
RPC 概念、Dubbo 架构、Hello World
- RPC:远程过程调用,像调本地方法一样调用远程服务。
- 角色:Provider 提供、Consumer 消费、Registry 注册、Monitor 监控。
- 接口契约:服务接口独立成 jar,双方共同依赖。
实训1.1 Dubbo 架构角色
说明 Dubbo 架构中的 Provider、Consumer、Registry、Monitor 角色。
Provider 提供服务、Consumer 消费服务、Registry 注册发现、Monitor 监控统计。
// Dubbo 核心角色
// 1. Provider:服务提供者,启动时向注册中心注册服务
// 2. Consumer:服务消费者,从注册中心订阅服务地址
// 3. Registry:注册中心(Zookeeper/Nacos),负责地址存储与通知
// 4. Monitor:监控中心,统计调用次数与耗时
public class DubboArch {
// 调用流程:Consumer -> Registry 获取地址 -> 直连 Provider
}
实训1.2 定义服务接口
定义 UserService 接口,供提供者实现、消费者调用。
接口独立成 jar 包,Provider 与 Consumer 共同依赖该接口。
public interface UserService {
String sayHello(String name);
User findById(Long id);
}
实训1.3 服务提供者实现
实现 UserService 接口并注册为 Dubbo 服务。
@DubboService 注解将实现暴露为 Dubbo 服务,注册到注册中心。
import org.apache.dubbo.config.annotation.DubboService;
@DubboService
public class UserServiceImpl implements UserService {
@Override
public String sayHello(String name) {
return "Hello, " + name + " from Dubbo";
}
@Override
public User findById(Long id) {
User u = new User();
u.setId(id);
u.setName("用户" + id);
return u;
}
}
单元2 · 服务提供者
配置、启动、多协议
- 提供者配置:application.name + registry.address + protocol。
- 发布服务:@DubboService 暴露实现,@EnableDubbo 开启。
- 多协议:protocols 同时发布 dubbo/rest 协议。
实训2.1 Provider 配置
在 application.yml 配置 Dubbo 应用名、注册中心与协议端口。
dubbo.application.name 应用名;registry.address 注册中心;protocol.port 服务端口。
dubbo:
application:
name: user-provider
registry:
address: nacos://127.0.0.1:8848
protocol:
name: dubbo
port: 20880
scan:
base-packages: com.helpme.service
实训2.2 启动 Provider
编写 Spring Boot 启动类启动 Dubbo 服务提供者。
@EnableDubbo 开启 Dubbo 自动配置,配合 scan 扫描 @DubboService。
import org.apache.dubbo.config.spring.context.annotation.EnableDubbo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
@EnableDubbo
public class UserProviderApplication {
public static void main(String[] args) {
SpringApplication.run(UserProviderApplication.class, args);
System.out.println("UserProvider 启动成功");
}
}
实训2.3 多协议发布
配置 dubbo 与 rest 双协议发布服务。
protocols 定义多协议,服务可同时通过 dubbo 与 REST 调用。
dubbo:
protocols:
dubbo:
name: dubbo
port: 20880
rest:
name: rest
port: 8081
server: netty
单元3 · 服务消费者
@DubboReference、直连、超时
- 消费者:@DubboReference 注入远程代理。
- 超时重试:timeout 超时、retries 重试次数。
- 直连:url 指定地址绕过注册中心调试。
实训3.1 Consumer 配置
配置消费者应用并注入远程服务调用。
@DubboReference 注入远程代理,像本地调用一样使用。
dubbo:
application:
name: user-consumer
registry:
address: nacos://127.0.0.1:8848
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.stereotype.Component;
@Component
public class UserConsumer {
@DubboReference
private UserService userService;
public String callHello(String name) {
return userService.sayHello(name);
}
}
实训3.2 超时与重试配置
为引用配置超时时间与重试次数。
timeout 毫秒超时,retries 失败重试次数;幂等接口可配重试。
dubbo:
consumer:
timeout: 3000
retries: 2
// 注解方式
@DubboReference(timeout = 5000, retries = 0)
private UserService userService;
实训3.3 直连提供者
绕过注册中心直连指定地址调试。
url 参数指定直连地址,适合开发调试。
@DubboReference(url = "dubbo://127.0.0.1:20880")
private UserService userService;
// 或配置方式
dubbo:
consumer:
url: dubbo://127.0.0.1:20880
单元4 · 注册中心
Zookeeper、Nacos 配置
- Zookeeper:zookeeper:// 地址,临时节点管理。
- Nacos:nacos:// 地址,健康检查与服务发现。
实训4.1 Zookeeper 注册中心
配置使用 Zookeeper 作为注册中心。
registry.address 使用 zookeeper:// 前缀;需引入 zookeeper 依赖。
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-registry-zookeeper</artifactId>
</dependency>
dubbo:
registry:
address: zookeeper://127.0.0.1:2181
实训4.2 Nacos 注册中心
配置使用 Nacos 作为注册中心。
dubbo-registry-nacos 依赖 + nacos:// 地址。
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-registry-nacos</artifactId>
</dependency>
dubbo:
registry:
address: nacos://127.0.0.1:8848
实训4.3 注册中心细节
说明服务注册的 key、临时节点与订阅通知机制。
Zookeeper 用临时节点,会话失效自动摘除;Nacos 支持服务健康检查。
// 注册 key 格式:
// /dubbo/com.helpme.UserService/providers/dubbo%3A%2F%2F...
// 临时节点:Provider 宕机自动删除
// 持久节点:手动管理,适合静态配置
// 通知机制:Consumer 监听目录变化,服务变更实时感知
public class RegistryNote {
// 以上为要点
}
单元5 · 负载均衡
内置策略、权重配置
- 策略:random 随机、roundrobin 轮询、leastactive 最少活跃、consistenthash 一致性哈希。
- 权重:provider.weight 影响负载概率。
- 扩展:实现 LoadBalance + SPI 自定义策略。
实训5.1 负载均衡策略
说明 Dubbo 内置的四种负载均衡策略。
random 随机、roundrobin 轮询、leastactive 最少活跃、consistenthash 一致性哈希。
// 四种策略
// 1. random:加权随机(默认)
// 2. roundrobin:加权轮询
// 3. leastactive:最少活跃调用数
// 4. consistenthash:一致性哈希,相同参数落同一节点
@DubboReference(loadbalance = "roundrobin")
private UserService userService;
实训5.2 权重配置
为不同提供者实例配置权重。
提供者配置 weight 属性,影响随机与轮询概率。
dubbo:
provider:
weight: 200
实训5.3 自定义负载均衡
简述自定义 LoadBalance 扩展点的实现方式。
实现 LoadBalance 接口 + @SPI 扩展点,通过 SPI 文件注册。
import org.apache.dubbo.common.URL;
import org.apache.dubbo.rpc.Invocation;
import org.apache.dubbo.rpc.Invoker;
import org.apache.dubbo.rpc.cluster.LoadBalance;
import java.util.List;
public class FirstLoadBalance implements LoadBalance {
@Override
public <T> Invoker<T> select(List<Invoker<T>> invokers, URL url, Invocation invocation) {
// 自定义选择逻辑:如始终选第一个
return invokers.get(0);
}
}
单元6 · 集群容错
容错策略、失败处理
- 容错:failover 切换、failfast 快失败、failsafe 忽略、failback 恢复。
- 重试:cluster + retries 组合,注意幂等。
- 扩展:实现 Cluster 接口自定义容错。
实训6.1 集群容错策略
列举 Dubbo 常用集群容错策略及适用场景。
failover 失败自动切换、failfast 快速失败、failsafe 失败安全、failback 失败恢复。
// failover:失败自动切换其它节点(默认,重试)
// failfast:只调用一次,失败立即报错
// failsafe:失败忽略,返回空结果
// failback:失败记录,定时重发
// forking:并行调用多个节点,取最快结果
@DubboReference(cluster = "failfast")
private UserService userService;
实训6.2 失败重试
配置 failover 重试 3 次调用用户服务。
cluster=failover + retries 控制重试次数,注意幂等性。
@DubboReference(cluster = "failover", retries = 3)
private UserService userService;
实训6.3 自定义容错
简述通过 Cluster SPI 扩展自定义容错策略。
实现 Cluster 接口生成 Invoker 装饰器,控制调用失败后的处理逻辑。
import org.apache.dubbo.rpc.Invoker;
import org.apache.dubbo.rpc.RpcException;
import org.apache.dubbo.rpc.cluster.Cluster;
import org.apache.dubbo.rpc.cluster.Directory;
public class MyCluster implements Cluster {
@Override
public <T> Invoker<T> join(Directory<T> directory) throws RpcException {
// 返回包装 Invoker,自定义容错逻辑
return new MyClusterInvoker<>(directory);
}
}
单元7 · 服务降级与直连
mock、本地伪装
- 降级:mock 指定兜底类或直接返回。
- 强制降级:force:return 直接返回,fail: 失败降级。
实训7.1 服务降级
为消费者配置 mock 降级返回兜底数据。
mock 指定降级类,服务不可用时返回兜底结果。
@DubboReference(mock = "com.helpme.mock.UserServiceMock")
private UserService userService;
实训7.2 编写 Mock 类
编写降级 Mock 类返回默认用户。
Mock 类实现同接口,方法内返回兜底数据,类名不能与接口同名。
public class UserServiceMock implements UserService {
@Override
public String sayHello(String name) {
return "服务暂不可用";
}
@Override
public User findById(Long id) {
User u = new User();
u.setId(id);
u.setName("默认用户");
return u;
}
}
实训7.3 强制降级
通过配置强制不发起远程调用直接走降级。
mock=force:return null 直接返回,mock=fail: 失败时才降级。
// 强制降级:不调用远程,直接返回
@DubboReference(mock = "force:return null")
private UserService userService;
// 失败降级:调用失败后返回
@DubboReference(mock = "fail:return null")
private UserService userService2;
单元8 · 多版本与分组
version、group 灰度发布
- 版本:version 多版本共存,灰度发布。
- 分组:group 隔离不同环境实现。
实训8.1 多版本服务
为服务指定版本并让消费者调用指定版本。
@DubboService(version) 与 @DubboReference(version) 匹配。
@DubboService(version = "1.0.0")
public class UserServiceImplV1 implements UserService {
@Override
public String sayHello(String name) { return "v1: Hello " + name; }
}
@DubboService(version = "2.0.0")
public class UserServiceImplV2 implements UserService {
@Override
public String sayHello(String name) { return "v2: Hello " + name; }
}
// 消费者指定版本
@DubboReference(version = "2.0.0")
private UserService userService;
实训8.2 服务分组
为不同环境配置服务分组隔离调用。
group 分组隔离,同一接口不同实现按组消费。
@DubboService(group = "gray")
public class UserServiceGrayImpl implements UserService {
}
@DubboService(group = "normal")
public class UserServiceNormalImpl implements UserService {
}
// 消费者按组引用
@DubboReference(group = "gray")
private UserService grayUserService;
实训8.3 灰度发布实践
说明利用 version/group 实现灰度发布的基本流程。
新版本发布为独立 version,部分消费者切新版本验证,稳定后全量。
// 灰度发布流程
// 1. 新版本 UserServiceImplV2 发布,version=2.0.0
// 2. 少量消费者引用 version=2.0.0 灰度验证
// 3. 稳定后所有消费者切到 2.0.0
// 4. 旧版本 1.0.0 保留观察,确认无问题后下线
@DubboReference(version = "2.0.0")
private UserService userService;
单元9 · 异步与泛化调用
AsyncContext、GenericService
- 异步:async=true 返回 CompletableFuture。
- AsyncContext:服务端异步处理。
- 泛化:GenericService.$invoke 免接口 jar 调用。
实训9.1 异步调用
配置消费者异步调用服务。
async=true 返回 CompletableFuture,异步处理结果。
@DubboReference(async = true)
private UserService userService;
public void asyncCall(String name) {
CompletableFuture<String> future = userService.sayHello(name);
future.whenComplete((result, ex) -> {
if (ex == null) {
System.out.println("异步结果:" + result);
}
});
}
实训9.2 异步服务端
服务端使用 AsyncContext 实现异步处理。
AsyncContext.start 提交异步任务,RpcContext 保留上下文。
import org.apache.dubbo.rpc.AsyncContext;
import org.apache.dubbo.rpc.RpcContext;
import java.util.concurrent.CompletableFuture;
@DubboService
public class AsyncServiceImpl implements AsyncService {
@Override
public CompletableFuture<String> doAsync(String name) {
return CompletableFuture.supplyAsync(() -> "Async: " + name);
}
}
实训9.3 泛化调用
使用 GenericService 不依赖接口 jar 包调用服务。
GenericService.$invoke 传入方法名、参数类型与值,泛化调用。
import org.apache.dubbo.config.ApplicationConfig;
import org.apache.dubbo.config.ReferenceConfig;
import org.apache.dubbo.config.RegistryConfig;
import org.apache.dubbo.rpc.service.GenericService;
public class GenericDemo {
public static void main(String[] args) {
ReferenceConfig<GenericService> ref = new ReferenceConfig<>();
ref.setApplication(new ApplicationConfig("generic-consumer"));
ref.setRegistry(new RegistryConfig("nacos://127.0.0.1:8848"));
ref.setInterface("com.helpme.UserService");
ref.setGeneric("true");
GenericService genericService = ref.get();
Object result = genericService.$invoke("sayHello",
new String[]{"java.lang.String"}, new Object[]{"World"});
System.out.println(result);
}
}
单元10 · 配置中心与动态配置
配置管理、动态调整
- 配置中心:config-center 动态调整配置。
- 优先级:方法 > 接口 > 全局。
- 外部化:${} 占位符引用环境配置。
实训10.1 配置中心
将 Dubbo 配置托管到 Nacos 配置中心。
config-center 配置中心地址,动态调整配置无需重启。
dubbo:
config-center:
address: nacos://127.0.0.1:8848
namespace: dubbo-config
实训10.2 动态配置覆盖
说明配置优先级:方法级 > 接口级 > 全局。
配置覆盖顺序:方法 > 接口 > 消费者全局 > 提供者全局 > 配置中心。
// 配置优先级(从高到低)
// 1. 方法级配置
// 2. 接口级配置
// 3. 消费者全局配置
// 4. 提供者全局配置
// 5. 配置中心默认配置
@DubboReference(timeout = 1000)
private UserService userService;
@DubboReference
private OrderService orderService;
实训10.3 外部化配置
将服务端口等敏感配置外部化到环境变量或配置文件。
通过 ${} 占位符引用外部配置,支持环境差异化。
dubbo:
protocol:
name: dubbo
port: ${DUBBO_PORT:20880}
registry:
address: ${REGISTRY_ADDRESS:nacos://127.0.0.1:8848}
单元11 · 监控与治理
Admin 控制台、Metrics、链路追踪
- Admin:服务查询、路由、动态配置、治理。
- Metrics:Prometheus 指标暴露 qps/rt。
- 追踪:Micrometer Tracing + Zipkin。
实训11.1 Dubbo Admin
说明 Dubbo Admin 控制台提供的治理能力。
Admin 提供服务查询、路由规则、动态配置、负载均衡调整。
// Dubbo Admin 功能
// 1. 服务查询:查看 Provider/Consumer 列表
// 2. 路由规则:条件路由、标签路由
// 3. 动态配置:调整超时、权重、Mock
// 4. 服务测试:在线调用接口
// 5. 服务治理:黑白名单、限流
// 访问:http://localhost:8080
public class AdminNote {
// 以上为要点
}
实训11.2 Metrics 监控
开启 Dubbo Metrics 并说明核心指标。
dubbo.metrics 暴露 qps、rt、成功失败次数等指标。
dubbo:
metrics:
enable: true
port: 9090
protocol: prometheus
// 指标示例
// dubbo_provider_qps:提供者 QPS
// dubbo_provider_rt_millis:平均响应时间
// dubbo_requests_total:请求总数
实训11.3 链路追踪集成
集成 Micrometer Tracing 实现 Dubbo 调用链追踪。
引入 micrometer-tracing 依赖 + zipkin 上报,调用链带 traceId。
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-metrics-api</artifactId>
</dependency>
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-tracing-bridge-zipkin</artifactId>
</dependency>
单元12 · 综合项目实训
综合运用所学知识完成项目
- 综合应用:接口契约 + 提供者实现 + 网关消费组合。
实训12.1 微服务用户中心 - 接口定义
定义用户中心 UserApi 接口(注册、查询、更新)。
接口独立成 API 模块,作为服务契约。
import java.util.List;
public interface UserApi {
User register(String name, String email);
User findById(Long id);
List<User> listByPage(int page, int size);
boolean updateEmail(Long id, String email);
}
实训12.2 微服务用户中心 - 提供者实现
实现 UserApi 并发布为 Dubbo 服务。
@DubboService 发布服务,Service 层组合仓储完成业务。
import org.apache.dubbo.config.annotation.DubboService;
import java.util.List;
@DubboService(version = "1.0.0", timeout = 5000)
public class UserApiImpl implements UserApi {
private final UserRepository userRepository;
public UserApiImpl(UserRepository userRepository) {
this.userRepository = userRepository;
}
@Override
public User register(String name, String email) {
User u = new User();
u.setName(name);
u.setEmail(email);
return userRepository.save(u);
}
@Override
public User findById(Long id) {
return userRepository.findById(id).orElse(null);
}
@Override
public List<User> listByPage(int page, int size) {
return userRepository.findAll();
}
@Override
public boolean updateEmail(Long id, String email) {
User u = findById(id);
if (u == null) return false;
u.setEmail(email);
userRepository.save(u);
return true;
}
}
实训12.3 微服务用户中心 - 消费者网关
在网关服务中引用 UserApi 对外提供 HTTP 接口。
网关层 @DubboReference 调用远程服务,暴露 REST API。
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/api/users")
public class UserGatewayController {
@DubboReference(version = "1.0.0", cluster = "failover", retries = 2)
private UserApi userApi;
@GetMapping("/{id}")
public User getUser(@PathVariable Long id) {
return userApi.findById(id);
}
@PostMapping
public User register(@RequestBody RegisterRequest req) {
return userApi.register(req.getName(), req.getEmail());
}
}