Dubbo RPC 服务调用
定位说明
Apache Dubbo 是阿里巴巴开源的高性能、轻量级 RPC 框架,定位为微服务框架的核心通信层。与 Spring Cloud 的 HTTP + REST 风格不同,Dubbo 使用自定义 RPC 协议(dubbo:// / triple://),在高吞吐、低延迟场景下具有显著优势。
Spring Cloud Alibaba 生态将 Dubbo 作为一等公民集成:通过 spring-cloud-starter-dubbo,Dubbo 服务可以直接复用 Nacos 注册中心,与 Spring Cloud 的 RestTemplate / Feign 调用互通,形成「HTTP 对外 + RPC 对内」的混合通信架构。
适用场景:
- 高并发内部服务调用(如交易 → 库存、订单 → 支付)
- 需要自定义序列化协议(Protobuf / Hessian2)的场景
- 已有 Dubbo 技术栈的团队平滑迁移到 Spring Cloud 生态
前置知识:读者应理解 RPC 基本概念(接口定义、序列化、代理),熟悉 Nacos 注册中心。
核心概念速览
| 角色 | 说明 | 对应 Spring Cloud 概念 |
|---|---|---|
| Provider(服务提供者) | 暴露服务的应用,将服务注册到注册中心 | @RestController |
| Consumer(服务消费者) | 调用远程服务的应用,从注册中心订阅服务 | RestTemplate / Feign |
| Registry(注册中心) | 存储服务地址信息,通知变更 | Nacos / Eureka |
| Protocol(协议) | RPC 通信协议(dubbo / triple / rest) | HTTP |
| Interface(服务接口) | 定义服务契约的 Java 接口 | Feign Interface |
环境准备
Maven 依赖
<dependencies>
<!-- Dubbo Spring Cloud Starter(含 Nacos 注册中心集成) -->
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
</dependency>
<!-- Nacos 注册中心 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!-- Nacos 作为 Dubbo 注册中心 -->
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-registry-nacos</artifactId>
</dependency>
</dependencies>
配置文件
dubbo:
application:
name: dubbo-provider # 应用名
logger: slf4j
protocol:
name: dubbo # 协议类型
port: 20880 # 协议端口
registry:
address: nacos://127.0.0.1:8848 # 注册中心地址
protocol: nacos
provider:
timeout: 3000 # 超时时间(ms)
retries: 2 # 重试次数
loadbalance: random # 负载均衡策略
核心用法
一、定义服务接口(API 模块)
Dubbo 最佳实践要求将服务接口独立为公共模块(xxx-api),Provider 和 Consumer 共同依赖此模块,实现契约优先。
// 位于 dubbo-api 模块
package com.example.dubbo.api;
public interface UserService {
/**
* 根据用户 ID 查询用户信息
*/
UserDTO getUserById(Long userId);
/**
* 创建用户并返回 ID
*/
Long createUser(UserDTO user);
}
二、服务提供者(Provider)
package com.example.dubbo.provider;
import com.example.dubbo.api.UserService;
import com.example.dubbo.api.UserDTO;
import org.apache.dubbo.config.annotation.DubboService;
@DubboService(version = "1.0.0", group = "user", timeout = 3000)
public class UserServiceImpl implements UserService {
@Override
public UserDTO getUserById(Long userId) {
// 实际场景中查询数据库
UserDTO user = new UserDTO();
user.setId(userId);
user.setName("张三");
user.setEmail("zhangsan@example.com");
return user;
}
@Override
public Long createUser(UserDTO user) {
// 保存到数据库并返回 ID
return 12345L;
}
}
启动类配置:
@SpringBootApplication
@EnableDubbo // 开启 Dubbo 自动配置
public class DubboProviderApplication {
public static void main(String[] args) {
SpringApplication.run(DubboProviderApplication.class, args);
}
}
三、服务消费者(Consumer)
package com.example.dubbo.consumer;
import com.example.dubbo.api.UserService;
import com.example.dubbo.api.UserDTO;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/users")
public class UserController {
@DubboReference(version = "1.0.0", group = "user", timeout = 3000, retries = 2)
private UserService userService;
@GetMapping("/{id}")
public UserDTO getUser(@PathVariable Long id) {
return userService.getUserById(id);
}
@PostMapping
public Long createUser(@RequestBody UserDTO user) {
return userService.createUser(user);
}
}
注意:
@DubboReference注入的userService是 Dubbo 框架生成的 RPC 代理对象,调用时底层通过 dubbo 协议与远端的 Provider 通信。
协议配置
Dubbo 支持多种 RPC 协议,选择策略如下:
| 协议 | 特点 | 适用场景 |
|---|---|---|
| dubbo | 基于 Netty,TCP 长连接,单连接多路复用 | 内部服务间高频小数据量调用 |
| triple | 基于 HTTP/2 + Protobuf,兼容 gRPC | 跨语言调用、网关穿透 |
| rest | 标准 HTTP RESTful | 对外暴露 API,与 Spring MVC 共享端口 |
| hessian | 基于 HTTP 短连接 | 兼容老系统 |
协议切换示例
dubbo:
protocol:
name: triple # 切换为 triple 协议(HTTP/2 + Protobuf)
port: 50051
serialization: protobuf
多协议暴露
同一服务可同时暴露多种协议:
dubbo:
protocols:
dubbo:
name: dubbo
port: 20880
triple:
name: triple
port: 50051
@DubboService(version = "1.0.0", protocol = {"dubbo", "triple"})
public class UserServiceImpl implements UserService { ... }
负载均衡
Dubbo 内置多种负载均衡策略,可通过 @DubboReference(loadbalance = "...") 指定:
| 策略 | 说明 | 适用场景 |
|---|---|---|
| random(默认) | 加权随机,按权重分配 | 通用场景 |
| roundrobin | 加权轮询,按顺序分配 | 各节点性能一致 |
| leastactive | 最少活跃调用数,优先选繁忙度低的节点 | 请求耗时差异大 |
| consistenthash | 一致性哈希,相同参数路由到同一节点 | 缓存命中率优化 |
| shortestresponse | 最短响应时间,优先选历史 RT 最短的节点 | 追求低延迟 |
@DubboReference(version = "1.0.0", loadbalance = "leastactive")
private UserService userService;
高级特性
一、服务版本与灰度发布
通过 version 和 group 实现多版本共存与灰度发布:
// Provider — 稳定版
@DubboService(version = "1.0.0", group = "stable")
public class UserServiceImplV1 implements UserService { ... }
// Provider — 灰度版
@DubboService(version = "1.1.0", group = "canary")
public class UserServiceImplV2 implements UserService { ... }
// Consumer — 指定灰度版本
@DubboReference(version = "1.1.0", group = "canary")
private UserService userService;
二、超时与重试
dubbo:
consumer:
timeout: 3000 # 全局超时(ms)
retries: 1 # 全局重试次数(不包含首次调用)
// 方法级别覆盖全局配置
@DubboReference(version = "1.0.0", timeout = 5000, retries = 0)
private UserService userService;
幂等性警告:Dubbo 失败自动重试会导致 Provider 端收到重复请求,Provider 端接口必须保证幂等性(如通过唯一请求 ID 去重)。
三、服务降级
// Consumer 端 mock 降级
@DubboReference(version = "1.0.0", mock = "com.example.fallback.UserServiceMock")
private UserService userService;
// 降级实现
public class UserServiceMock implements UserService {
@Override
public UserDTO getUserById(Long userId) {
return UserDTO.fallback("服务暂不可用"); // 返回兜底数据
}
}
四、与 Sentinel 集成实现熔断
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-sentinel-spring-boot-starter</artifactId>
</dependency>
通过 Sentinel Dashboard 对 Dubbo 服务配置流量控制和熔断降级规则,无需修改业务代码。
Dubbo 与 Spring Cloud HTTP 调用对比
| 维度 | Dubbo RPC | Spring Cloud HTTP(Feign/RestTemplate) |
|---|---|---|
| 通信协议 | 自定义 TCP 协议(dubbo/triple) | HTTP/1.1 或 HTTP/2 |
| 序列化 | Hessian2 / Protobuf / Kryo | JSON(Jackson) |
| 性能 | 高吞吐、低延迟(~1ms 级别) | 相对较高延迟(~5-10ms 级别) |
| 连接模型 | TCP 长连接,多路复用 | HTTP 短连接(可配连接池) |
| 跨语言 | triple 协议支持,dubbo 协议仅 Java | 天然跨语言 |
| 服务治理 | 内置路由、分组、多版本 | 依赖 Spring Cloud Gateway |
| 学习成本 | 中等(需理解接口契约) | 低(REST 风格直观) |
| 适用场景 | 内部微服务高性能调用 | 对外 API / 跨语言调用 |
混合架构推荐:内部服务间使用 Dubbo RPC,对前端/第三方暴露接口使用 Spring Cloud Gateway + HTTP。
面试考点
1. Dubbo 的调用流程是怎样的?
Consumer → 本地代理(Proxy)→ 路由(Router)→ 负载均衡(LoadBalance)→ 过滤器链(Filter)→ 网络传输(Netty)→ Provider 端过滤器链 → 反射调用实现类 → 逆序返回结果。
2. Dubbo 和 Feign 的本质区别是什么?何时选 Dubbo?
- 通信模型:Dubbo 是 RPC 框架(自定义协议 + TCP 长连接),Feign 是声明式 HTTP 客户端(HTTP + 短连接)。
- 性能:Dubbo 自定义协议更轻量,序列化更紧凑(Hessian2 vs JSON),高并发场景下延迟更低。
- 选型建议:内部微服务间高频调用选 Dubbo;对外 API / 跨语言 / 与前端交互选 Feign 或 RestTemplate。
3. Dubbo 的负载均衡策略有哪些?默认是什么?
六大策略:Random(默认,加权随机)、RoundRobin(加权轮询)、LeastActive(最少活跃数)、ConsistentHash(一致性哈希)、ShortestResponse(最短响应时间)。默认加权随机,权重可在 Nacos 中动态配置。
4. Dubbo 如何实现服务降级?
- Consumer 端 Mock:
@DubboReference(mock = "fallbackClass"),RPC 调用失败时返回兜底数据。 - 集成 Sentinel:在 Sentinel Dashboard 配置熔断规则,达到阈值后自动降级。
5. triple 协议相比 dubbo 协议的优势?
triple 基于 HTTP/2 + Protobuf,兼容 gRPC 生态,天然支持流式调用(Streaming)、跨语言互操作,并且可以通过标准 HTTP 网关(如 Higress、Envoy)代理,与云原生 Service Mesh 接轨。dubbo 协议性能略优但仅限 Java。
参考资源:
- Apache Dubbo 官方文档:https://dubbo.apache.org
- Dubbo Spring Boot Starter:https://github.com/apache/dubbo-spring-boot-project
- Dubbo + Nacos 注册中心集成:https://dubbo.apache.org/zh-cn/overview/mannual/java-sdk/reference-manual/registry/nacos/