这是一篇 2018 年 7 月整理的 Dubbo 系列笔记。内容按当年的视角写就:Dubbo 2.5.x/2.6.x 时代、
com.alibaba.dubbo包名、ZooKeeper 还是主流的注册中心、Spring Boot 注解式配置刚刚兴起。命令、写法都保留当年的风格——这正是把历史笔记迁移到新博客的价值。
Dubbo 是什么
Dubbo 是一个分布式服务框架,致力于提供高性能和透明化的 RPC 远程服务调用方案,以及 SOA 服务治理方案。
拆开看这句话的三个关键词:
- 分布式服务框架:当单体应用拆成多个服务后,服务之间需要互相调用,Dubbo 就是用来打通服务间调用的基础设施。
- 高性能和透明化的 RPC 远程服务调用:像调用本地方法一样调用远程服务(透明化),并且这个过程要快(高性能)。
- SOA 服务治理:服务多了以后,要有注册中心管理服务地址、负载均衡分发流量、容错机制处理失败——这一整套”治理”能力。
为什么需要 RPC:从单体到分布式
单体应用时代,所有功能在一个进程里,方法调用就是普通的方法调用。一旦拆分成多个服务(不同进程、甚至不同机器),服务间调用就变成了网络调用——这时遇到三个问题:
- 网络通信:用什么协议、怎么序列化?Socket 裸写太痛苦。
- 寻址:服务部署在多台机器上,调用方怎么知道该连哪台?
- 治理:服务挂了怎么办?流量怎么分发?超时重试怎么处理?
RPC(Remote Procedure Call,远程过程调用)要解决的核心就是:让远程调用像本地调用一样简单。而 Dubbo 在 RPC 之上,还补齐了服务治理的整块拼图。
Dubbo 能解决什么问题
以当年的视角,Dubbo 的核心价值可以归纳为六点:
| 能力 | 说明 |
|---|---|
| 透明化 RPC | 基于接口 + 注解/XML 声明,像调本地方法一样调远程服务 |
| 负载均衡 | 内置 Random、RoundRobin、LeastActive、一致性哈希四种策略 |
| 集群容错 | Failover(失败重试)、Failfast、Failsafe、Failback、Forking 五种模式 |
| 服务注册与发现 | 基于 ZooKeeper 等注册中心,服务自动注册、自动发现 |
| 服务治理 | 路由规则、动态配置、权重调整、监控统计 |
| 高可用 | 服务降级、集群容错、多注册中心,单点故障不影响整体 |
Dubbo 的核心角色
Dubbo 架构中有四个核心角色(外加一个容器):
------------- 注册中心 Registry(ZooKeeper) -------------
/ 注册/订阅 | 通知地址变化 \
/ | \
Provider(服务提供者) Consumer(服务消费者)
启动时向注册中心注册 启动时向注册中心订阅
启动时开启 Dubbo 协议端口 本地维护服务地址列表
\ | /
\------------------------ Monitor(监控中心)----------------/
统计调用次数、调用时间、成功失败次数
| 角色 | 职责 |
|---|---|
| Provider | 服务提供者,暴露服务接口,向注册中心注册 |
| Consumer | 服务消费者,从注册中心订阅服务地址,发起远程调用 |
| Registry | 注册中心,服务地址的注册与发现(ZooKeeper 为主流) |
| Monitor | 监控中心,统计调用次数、耗时、成败(可选) |
| Container | 容器,管理 Provider 的生命周期(独立部署时用) |
一次完整调用的流程:
1. Provider 启动 → 向 Registry 注册自己的服务地址(IP + 端口)
2. Consumer 启动 → 向 Registry 订阅需要的服务
3. Registry 把地址列表推送给 Consumer
4. Consumer 基于地址列表,按负载均衡策略选一台 Provider
5. Consumer 发起 RPC 调用(dubbo 协议、hessian2 序列化)
6. 调用信息上报 Monitor(统计调用量、耗时、成败)
7. Provider 地址变化(上线/下线/权重调整)→ Registry 实时通知 Consumer
一个最简示例
当年 Dubbo 最常用的接入方式是 Spring + XML 配置(Spring Boot 注解式配置当时也已经开始流行)。先看接口定义:
// 服务接口(放公共模块,Provider 和 Consumer 都要依赖)
public interface UserService {
String getUserName(Long id);
}
服务提供者 Provider(spring 配置文件 provider.xml):
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:dubbo="http://code.alibabatech.com/schema/dubbo">
<!-- 应用名 -->
<dubbo:application name="user-provider"/>
<!-- 注册中心地址 -->
<dubbo:registry address="zookeeper://10.129.83.213:2181"/>
<!-- 用 dubbo 协议在 20880 端口暴露服务 -->
<dubbo:protocol name="dubbo" port="20880"/>
<!-- 声明要暴露的接口 -->
<dubbo:service interface="com.example.UserService" ref="userServiceImpl"/>
</beans>
// 服务实现类
public class UserServiceImpl implements UserService {
@Override
public String getUserName(Long id) {
return "user-" + id;
}
}
服务消费者 Consumer(consumer.xml):
<dubbo:application name="user-consumer"/>
<dubbo:registry address="zookeeper://10.129.83.213:2181"/>
<!-- 引用远程接口,像本地 Bean 一样注入使用 -->
<dubbo:reference id="userService" interface="com.example.UserService"/>
// 使用:跟调本地方法一模一样
@Autowired
private UserService userService;
String name = userService.getUserName(1001L); // 实际是远程调用
注意
com.example接口来自公共依赖包,Provider 实现它、Consumer 引用它——Dubbo 的”透明化”就建立在接口共享的基础上。
Dubbo 与 HTTP 接口、Spring Cloud 的区别
当年面试几乎必问”你们为什么用 Dubbo 不用 HTTP?“以及”Dubbo 和 Spring Cloud 怎么选?“,整理成对比:
| 维度 | Dubbo RPC | HTTP 接口(如 REST) | Spring Cloud |
|---|---|---|---|
| 通信协议 | 自定义 dubbo 协议(TCP 长连接) | HTTP/1.1 | 默认 HTTP(REST) |
| 序列化 | hessian2 等(二进制,体积小) | JSON(体积大) | JSON |
| 性能 | 高(二进制 + 长连接 + 连接复用) | 中 | 中 |
| 服务治理 | 强(负载均衡/容错/路由/降级内置) | 需自研 | 组件多(Ribbon/Hystrix 等) |
| 服务注册 | ZooKeeper 等 | 需自研 | Eureka/Nacos 等 |
| 学习成本 | 中(配置较繁琐) | 低 | 中高(组件多) |
| 适用场景 | 内部服务间高性能调用 | 跨系统、开放 API | 全家桶微服务生态 |
实践中的选择:内部服务间追求性能 → Dubbo;对外暴露 API、跨语言集成 → HTTP/REST;追求完整微服务生态且重团队协作 → Spring Cloud。三者不冲突,很多系统内部用 Dubbo、对开放 Dubbo 无法暴露的接口用 HTTP 网关。
小结
- Dubbo = 高性能透明化 RPC + SOA 服务治理。
- 核心角色:Provider、Consumer、Registry(ZooKeeper)、Monitor。
- 核心能力:透明化调用、负载均衡、集群容错、服务注册发现、服务治理、高可用。
- 与 HTTP 相比性能更高、治理更强;与 Spring Cloud 相比更轻、专注 RPC 场景。
下一篇 《Dubbo 服务拆分与架构设计:子系统划分的四大原则》 讲分布式改造时服务该怎么拆。