Dubbo + Nacos 服务治理
概述
Dubbo 3.x 在 RPC 调用基础上提供了丰富的服务治理能力。结合 Nacos 注册中心和配置中心,可以实现动态路由、服务降级、限流等治理功能。
核心架构
Dubbo Provider(服务提供者)
├── 启动时向 Nacos 注册服务
├── 定期发送心跳(续约)
└── 暴露 Dubbo 协议端口
Dubbo Consumer(服务消费者)
├── 从 Nacos 订阅服务列表
├── 监听服务变更(实时更新)
└── 根据路由规则选择调用实例
Nacos(注册中心 + 配置中心)
├── 服务注册与发现
├── 权重/路由配置
└── 动态配置推送一、Dubbo 3.x 整合 Nacos
1.1 依赖
xml
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
<version>3.2.14</version>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-registry-nacos</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.nacos</groupId>
<artifactId>nacos-client</artifactId>
</dependency>1.2 提供者配置
yaml
# application.yml(Provider)
dubbo:
application:
name: order-service
registry:
address: nacos://192.168.1.100:8848
parameters:
namespace: dubbo-dev
protocol:
name: dubbo
port: -1 # 随机端口(避免端口冲突)
provider:
timeout: 3000
retries: 2 # 重试次数
loadbalance: roundrobin # 负载均衡策略
weight: 100 # 实例权重1.3 消费者配置
yaml
# application.yml(Consumer)
dubbo:
application:
name: order-web
registry:
address: nacos://192.168.1.100:8848
parameters:
namespace: dubbo-dev
consumer:
timeout: 3000
retries: 0 # 消费者重试(注意幂等性)
check: false # 启动时不检查依赖服务
loadbalance: roundrobin1.4 接口定义与使用
java
// API 接口(公共 Jar 包)
public interface OrderService {
Order createOrder(OrderRequest request);
Order getOrder(Long orderId);
Page<Order> listOrders(Long userId, int page, int size);
}
// Provider 实现
@DubboService
public class OrderServiceImpl implements OrderService {
@Override
public Order createOrder(OrderRequest request) {
return orderRepository.save(request.toOrder());
}
}
// Consumer 调用
@Service
public class OrderFacadeService {
@DubboReference
private OrderService orderService;
public Order createOrder(OrderRequest request) {
return orderService.createOrder(request);
}
}二、路由策略
2.1 权重路由
yaml
# Nacos 中设置实例元数据(权重)
# Provider 配置
dubbo:
provider:
parameters:
weight: 200 # 权重 200(默认 100)java
// 权重路由配置:实例权重 100 vs 200,流量分配比例 1:2
// 适用于:新版本灰度 20% 流量
@Configuration
public class DubboRouteConfig {
@Bean
public RouterFactory weightRouter() {
// 条件路由:version=v2 的实例权重降低
return RouterFactory.getInstance();
}
}2.2 同区域优先
yaml
# Provider 注册时携带地域标签
dubbo:
provider:
parameters:
region: beijing # 区域
zone: beijing-zone1 # 可用区
# Consumer 配置
dubbo:
consumer:
parameters:
region: beijing
zone: beijing-zone1java
// 同区域优先路由
// 优先调用同区域的 Provider,跨区域为降级方案
@Service
public class RegionAwareService {
@DubboReference(parameters = {
"router", "region-aware" # 启用区域感知路由
})
private OrderService orderService;
}2.3 参数路由
java
// 条件路由:根据方法参数路由到不同的 Provider 版本
// 场景:VIP 用户使用 V2 版本,普通用户使用 V1 版本
@DubboReference(parameters = {
"router", "condition"
})
private OrderService orderService;
// Nacos 中配置条件路由
// dubbo.route.condition.order-service=
// => method=getOrder & arguments[0]=10000+ ~> version=v2
// => method=getOrder ~> version=v1三、动态配置
3.1 Nacos 动态调整
java
// Nacos 配置中心监听配置变更
@Component
public class DubboConfigListener
implements CommandLineRunner {
@Autowired
private ConfigService configService;
@Override
public void run(String... args) {
// 监听 Dubbo 动态配置
String dataId = "dubbo:order-service";
String group = "DUBBO_GROUP";
configService.addListener(dataId, group, new Listener() {
@Override
public Executor getExecutor() {
return Executors.newSingleThreadExecutor();
}
@Override
public void receiveConfigInfo(String configInfo) {
// 配置变更示例:
// dubbo.provider.timeout=5000
// dubbo.provider.retries=3
// dubbo.provider.weight=50
log.info("Dubbo config updated: {}", configInfo);
// 动态更新配置
DynamicConfiguration config = DynamicConfigurationFactory
.getInstance().getDynamicConfiguration();
config.setProperties(configInfo);
}
});
}
}3.2 配置格式
yaml
# Nacos dataId: dubbo:order-service
# Nacos group: DUBBO_GROUP
# 超时调整(临时增加超时)
dubbo.provider.timeout=5000
# 降级配置
dubbo.reference.order-service.mock=force:return null
# 或
dubbo.reference.order-service.mock=com.example.OrderServiceMock
# 限流
dubbo.provider.filter=tps
dubbo.provider.tps=100
# 路由
dubbo.router.order-service.condition=
-> serviceName=order-service
& method=createOrder
~> weight=50四、服务降级
4.1 Mock 降级
java
// 接口定义
public interface InventoryService {
boolean deductStock(Long productId, Integer quantity);
}
// Mock 降级类(类名规则:接口名 + Mock 后缀)
@Component
public class InventoryServiceMock implements InventoryService {
@Override
public boolean deductStock(Long productId, Integer quantity) {
// 服务调用失败时返回 Mock 数据
log.warn("InventoryService degraded, returning mock");
// 如果降级频率过高,触发告警
Metrics.counter("inventory.degraded").increment();
return true; // 降级:返回成功,允许下单
}
}
// Consumer 使用 Mock
@Service
public class OrderCreateService {
@DubboReference(
mock = "com.example.InventoryServiceMock",
timeout = 2000,
cluster = "failover"
)
private InventoryService inventoryService;
}4.2 动态降级
java
// Nacos 动态降级配置
// 场景:大促期间,非核心服务直接降级
// Nacos 配置变更触发降级
@Component
public class DynamicDegradation {
@DubboReference(mock = "true") // mock="true" 使用默认 mock
private CouponService couponService;
@DubboReference(mock = "true")
private RecommendService recommendService;
// 收到降级指令后,切换 mock 逻辑
@NacosConfigListener(dataId = "degrade-config", group = "DUBBO")
public void onDegradeConfig(String config) {
JSONObject configJson = JSON.parseObject(config);
if (configJson.getBooleanValue("degradeCoupon")) {
// 优惠券服务降级:不发放优惠券
log.warn("Coupon service degraded");
}
if (configJson.getBooleanValue("degradeRecommend")) {
// 推荐服务降级:返回默认推荐
log.warn("Recommend service degraded");
}
}
}五、限流
5.1 TPS 限流
yaml
# Provider 端限流
dubbo:
provider:
filter: tps
tps: 100 # 每秒最多处理 100 个请求
tps.interval: 60000 # 统计周期(毫秒)
tps.strategy: sliding # 限流策略:fixed/sliding5.2 方法级别限流
yaml
# 方法级别不同的限流阈值
dubbo:
provider:
parameters:
createOrder.tps: 50 # 下单接口限流 50
queryOrder.tps: 500 # 查询接口限流 5005.3 自定义限流过滤器
java
@Activate(group = CommonConstants.PROVIDER, order = -10000)
public class CustomRateLimitFilter implements Filter {
private final RateLimiter rateLimiter = RateLimiter.create(200); // Guava RateLimiter
@Override
public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
if (!rateLimiter.tryAcquire(100, TimeUnit.MILLISECONDS)) {
// 限流:返回异常
return AsyncRpcResult.newDefaultAsyncResult(
new RpcException(RpcException.LIMIT_EXCEEDED_EXCEPTION,
"Rate limit exceeded"),
invocation);
}
return invoker.invoke(invocation);
}
}六、链路追踪集成
6.1 SkyWalking 整合
xml
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
</dependency>properties
# SkyWalking Agent 自动拦截 Dubbo 调用
# 无需额外配置,Agent 自动处理 Dubbo 协议
# 跨服务 TraceId 自动通过 Dubbo Attachment 传播6.2 Sleuth 整合
yaml
# application.yml
spring:
sleuth:
propagation-keys: dubbo_tag # 透传 Dubbo 标签
dubbo:
consumer:
filter: tracing # 启用 Sleuth 追踪
provider:
filter: tracingxml
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-sleuth</artifactId>
</dependency>七、灰度发布
7.1 版本路由
yaml
# Provider 注册时携带版本号
dubbo:
provider:
parameters:
version: v2
# Nacos 中配置条件路由
# 按用户灰度:user_id % 100 < 5 的请求路由到 v2
# 按请求头:x-version=v2 的路由到 v2java
// 灰度发布实现
@DubboReference(parameters = {
"router", "condition",
"condition.router", "=> version=v2 ~> weight=5" # 5% 流量到 v2
})
private OrderService orderService;八、总结
| 知识点 | 说明 |
|---|---|
| 注册中心 | Nacos 服务注册、发现、心跳 |
| 权重路由 | 按实例权重分配流量 |
| 同区域优先 | 优先同区域/同可用区调用 |
| 参数路由 | 按方法参数路由到不同版本 |
| 动态配置 | Nacos 推送超时/重试/权重 |
| 服务降级 | Mock 降级 + 动态降级配置 |
| 限流 | TPS 限流 + 方法级别限流 |
| 链路追踪 | SkyWalking 无侵入 + Sleuth |
| 灰度发布 | 条件路由 + 版本权重 |
参考链接: