一、Dubbo基础概念
阿里巴巴公司开源的一个高性能、轻量级的Java RPC框架,后被Apache收购。
- 架构:

Service Provider:服务提供者,负责实现业务逻辑并将服务注册到注册中心。
Registry:注册中心,管理服务提供者和消费者的地址列表及状态。
Service Consumer:服务消费者,通过注册中心发现服务并发起远程调用。

1. 核心组件
Dubbo 的架构主要包括以下几个核心组件:
- Provider(服务提供者):暴露服务的服务提供方,负责实现服务,并将服务注册到注册中心。
- Consumer(服务消费者):调用远程服务的服务消费方,通过注册中心发现服务,并发起远程调用。
- Registry(注册中心):管理服务提供者和消费者的地址列表及状态,支持服务的动态注册与发现。常见的注册中心实现有 ZooKeeper、Nacos 等。
- Monitor(监控中心):收集服务调用的统计信息,如调用次数、成功率、平均耗时等,用于服务治理和性能优化。
- Container(容器):服务运行的容器,如 Spring 容器、Jetty 容器等,负责启动和管理服务提供者和消费者。
2. 核心流程

以下6个方法是 Dubbo 核心流程的关键动作,覆盖了从服务启动到调用监控的全链路。
核心结论:start 是启动基础,register/subscribe/notify 支撑服务注册发现,invoke 实现远程调用,count 负责监控统计,共同构成 Dubbo 核心运行逻辑。
start:启动初始化方法
- 作用于 Container(容器)、Provider(服务提供者)、Consumer(服务消费者)。
- 触发组件初始化和启动,比如容器启动服务实例、Provider 加载服务接口、Consumer 初始化本地代理。
- 是所有后续操作(注册、订阅、调用)的前提。
register:服务注册方法
- 主要由 Provider 调用,目标是 Registry(注册中心)。
- Provider 启动后通过该方法,将服务接口、地址、版本号等信息提交给注册中心。
- 注册中心接收后,更新服务列表并持久化(如 ZooKeeper 的节点存储)。
subscribe:服务订阅方法
- 主要由 Consumer 调用,目标是 Registry(注册中心)。
- Consumer 启动后通过该方法,向注册中心声明需要调用的服务名称。
- 注册中心基于订阅信息,筛选对应的 Provider 地址列表并返回给 Consumer。
notify:变更通知方法
- 主要由 Registry 主动调用,接收方是 Consumer。
- 当 Provider 上下线、地址变更时,注册中心通过该方法推送最新服务列表给 Consumer。
- 确保 Consumer 始终持有可用的 Provider 地址,支持服务动态扩容缩容。
invoke:远程调用方法
- 由 Consumer 发起,通过本地代理(Stub)触发,目标是 Provider。
- 封装调用参数、协议转换(如 Dubbo 协议),通过网络传输将请求发送给 Provider。
- Provider 接收后执行业务逻辑,通过该方法将结果返回给 Consumer。
count:监控统计方法
- 由 Provider 和 Consumer 调用,目标是 Monitor(监控中心)。
- 实时上报调用次数、成功率、平均耗时、超时次数等核心指标。
- 监控中心通过统计数据支撑服务治理,比如熔断、限流、性能优化。
方法间关联逻辑
- 启动顺序:start → register(Provider 侧)/ subscribe(Consumer 侧)。
- 动态更新:register 触发 Registry 数据变更 → notify 同步给 Consumer。
- 调用链路:subscribe 获取地址 → invoke 执行远程调用 → count 上报监控数据。
3. 主要特性
- 透明化的远程方法调用:开发者只需编写本地方法调用的代码,无需关心底层的网络通信细节。
- 智能容错和负载均衡:Dubbo 提供了多种负载均衡策略(如随机、轮询、最少活跃调用数等),并在服务调用失败时自动切换到其他服务提供者。
- 服务自动注册与发现:服务提供者和消费者通过注册中心进行服务的注册和发现,简化了服务的管理和维护。
- 高性能:Dubbo 使用 Netty 作为网络通信框架,支持高效的异步非阻塞 I/O 操作。
- 丰富的配置管理:支持多种配置方式(如 XML、注解、API 等),方便开发者根据需求进行配置。
二、第一个Dubbo Demo
配套源码:gitlab仓库
首先,在服务器上部署zookeeper并运行,可以参考我的另一篇教程:https://blog.youkuaiyun.com/Tracycoder/article/details/142792750
注意事项:
- 生产者、消费者中服务的包路径一定要一致,不然会导致注册和消费失败。
- 先启动生产者,再启动消费者,不然会启动失败。
- 各依赖的版本一定要兼容,不然项目会启动失败。
1. 生产者工程
(1)目录结构

(2)依赖
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>dubbo_study_provider</artifactId>
<version>1.0-SNAPSHOT</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.5.4</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<dependencies>
<!-- Spring Boot Starter -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<!-- Dubbo Starter -->
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
<version>3.2.0</version>
</dependency>
<!-- Zookeeper Client -->
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-framework</artifactId>
<version>5.4.0</version>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-recipes</artifactId>
<version>5.4.0</version>
</dependency>
<dependency>
<groupId>org.javassist</groupId>
<artifactId>javassist</artifactId>
<version>3.29.2-GA</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.curator/curator-x-discovery-server -->
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-x-discovery-server</artifactId>
<version>5.4.0</version>
</dependency>
<!-- Spring Boot Test Starter -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>
(3)配置文件
applicaiton.yml
server:
port: 8080
# Dubbo
dubbo:
application:
name: dubbo_provider
registry:
address: zookeeper://你的zookeeperIP:2181
protocol:
name: dubbo
port: 20880
(4)启动类
package tracy;
import org.apache.dubbo.config.spring.context.annotation.EnableDubbo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
@EnableDubbo(scanBasePackages = "tracy.provider.service")
public class ProviderApplication {
public static void main(String[] args) {
System.setProperty("zookeeper.sasl.client", "false");
SpringApplication.run(ProviderApplication.class, args);
System.out.println("provider服务启动成功!!!");
}
}
(5)生产者服务
package tracy.provider.service;
public interface HelloService {
String sayHello(String name);
}
package tracy.provider.service;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.stereotype.Component;
@DubboService(version = "1.0.0")
@Component
public class HelloServiceImpl implements HelloService {
@Override
public String sayHello(String name) {
return "hello "+name+"!";
}
}
2. 消费者工程
(1)目录结构

(2)依赖
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>dubbo_study_consumer</artifactId>
<version>1.0-SNAPSHOT</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.5.4</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<dependencies>
<!-- Spring Boot Starter -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- Dubbo Starter -->
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
<version>3.2.0</version>
</dependency>
<!-- Zookeeper Client -->
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-framework</artifactId>
<version>5.4.0</version>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-recipes</artifactId>
<version>5.4.0</version>
</dependency>
<dependency>
<groupId>org.javassist</groupId>
<artifactId>javassist</artifactId>
<version>3.29.2-GA</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.curator/curator-x-discovery-server -->
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-x-discovery-server</artifactId>
<version>5.4.0</version>
</dependency>
<!-- Spring Boot Test Starter -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>
(3)配置文件
application.yml
server:
port: 8081
# Dubbo
dubbo:
application:
name: dubbo_consumer
registry:
address: zookeeper://你的zookeeperIP:2181
consumer:
check: false # 设置为 false,避免消费者启动时检查提供者状态
(4)启动类
package tracy;
import org.apache.dubbo.config.spring.context.annotation.EnableDubbo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
@EnableDubbo
public class ConsumerApplication {
public static void main(String[] args) {
System.setProperty("zookeeper.sasl.client", "false");
SpringApplication.run(ConsumerApplication.class, args);
System.out.println("consumer服务启动成功!!!");
}
}
(5)服务接口
package tracy.provider.service;
public interface HelloService {
String sayHello(String name);
}
(6)controller接口
package tracy.controller;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import tracy.provider.service.HelloService;
@RestController
@RequestMapping("/hello")
public class HelloController {
@DubboReference // 使用 DubboReference 注解引用远程服务
private HelloService helloService;
@GetMapping("/sayHello")
public String sayHello(@RequestParam String name) {
return helloService.sayHello(name);
}
}
3. 功能测试
先启动zookeeper,然后启动provider,最后启动consumer。
然后在接口测试工具中访问接口:

访问成功!
Dubbo 的容错和负载均衡是服务治理的核心能力,均基于 Dubbo 的 SPI(Service Provider Interface)扩展机制 实现,支持灵活配置和自定义扩展。以下分别从「核心原理、常用实现、配置方式」三方面详细说明:
三、Dubbo 容错机制(Fault Tolerance)
核心原理
Dubbo 的容错机制由 Cluster 组件主导:
- 消费者发起调用时,
Registry会返回服务的所有提供者列表(Invoker集合); Cluster会将多个Invoker包装成一个集群Invoker(屏蔽多节点细节);- 当调用失败时,集群
Invoker会按照预设的容错策略处理异常(重试、降级、忽略等)。
核心接口:org.apache.dubbo.rpc.cluster.Cluster,Dubbo 内置多种实现,也支持自定义。
常用容错策略(内置实现)
Dubbo 2.7+ 内置 7 种核心容错策略,可直接通过配置指定,优先级:方法级 > 接口级 > 全局级:
| 策略名称 | 英文标识 | 核心逻辑 | 适用场景 |
|---|---|---|---|
| 失败自动切换 | failover | 调用失败后,自动切换到其他服务提供者(默认重试 2 次,可配置) | 读操作(查询)、非幂等写操作(需谨慎) |
| 快速失败 | failfast | 调用失败后立即抛出异常,不重试、不切换 | 写操作(新增/修改/删除)、幂等性要求高的场景 |
| 失败安全 | failsafe | 调用失败后忽略异常,返回空结果或默认值 | 非核心功能(日志采集、统计上报) |
| 失败重试 | failretry | 只重试当前服务提供者,不切换其他节点(区别于 failover) | 服务节点不稳定但需确保同一节点重试的场景 |
| 并行调用 | forking | 同时调用多个服务提供者,取第一个成功结果返回(默认并行数 2) | 响应时间要求高、服务节点可靠性低的场景 |
| 广播调用 | broadcast | 广播调用所有服务提供者,任意节点失败则整体失败 | 服务同步(如缓存更新、配置推送) |
| 服务降级 | mock | 调用失败后,返回预设的降级结果(需配合 mock 实现) | 服务熔断、流量峰值降级 |
在微服务架构中,服务降级是一种核心的「自我保护机制」—— 当系统面临流量峰值、依赖服务故障、资源耗尽(CPU / 内存 /
数据库连接池)等异常场景时,主动关闭或简化非核心功能,释放系统资源,确保核心业务(如下单、支付、登录)的可用性和稳定性。
简单说:降级的本质是 “取舍” —— 牺牲非核心功能的完整性,换取核心功能的 “存活”,避免系统整体雪崩。
关键细节:
failover是默认策略,重试次数通过retries配置(默认 2 次,即最多调用 3 次:1 次原始 + 2 次重试);forking需配置并行数forks="3",通过线程池并行调用;mock策略需配合mock配置(如mock="return null"或自定义 mock 类)。
在微服务架构中,服务降级是一种核心的「自我保护机制」——当系统面临流量峰值、依赖服务故障、资源耗尽(CPU/内存/数据库连接池)等异常场景时,主动关闭或简化非核心功能,释放系统资源,确保核心业务(如下单、支付、登录)的可用性和稳定性。
简单说:降级的本质是“取舍” ——牺牲非核心功能的完整性,换取核心功能的“存活”,避免系统整体雪崩。
服务降级与相关概念的区别
很多人会把「降级」和「容错」「熔断」「限流」混淆:
| 概念 | 核心逻辑 | 触发条件 | 核心目的 |
|---|---|---|---|
| 服务降级 | 主动简化/关闭非核心功能,返回兜底结果 | 流量过载、资源不足、主动运维 | 保障核心功能可用 |
| 服务容错 | 调用失败后,按预设策略处理(重试、切换节点、忽略错误)(如Dubbo的failover) | 依赖服务调用失败(超时、报错) | 解决“单个服务调用失败”的问题 |
| 服务熔断 | 当依赖服务故障率达阈值时,自动“断开”调用,直接返回降级结果(如Sentinel熔断) | 依赖服务连续失败(故障率超标) | 防止故障扩散到上游服务 |
| 服务限流 | 限制单位时间内的请求数,超过阈值的请求直接拒绝或排队 | 流量突增(超过系统处理能力) | 保护系统不被流量击垮 |
自定义容错策略
若内置策略不满足需求,可通过 SPI 扩展自定义:
- 实现
Cluster接口(或继承AbstractCluster):
public class CustomCluster implements Cluster {
@Override
public <T> Invoker<T> join(Directory<T> directory) throws RpcException {
// 自定义容错逻辑:如「失败后先降级,再重试」
return new CustomClusterInvoker<>(directory);
}
// 实现集群 Invoker(核心逻辑,处理调用失败后的逻辑)
private static class CustomClusterInvoker<T> extends AbstractClusterInvoker<T> {
@Override
protected Result doInvoke(Invocation invocation, List<Invoker<T>> invokers, LoadBalance loadbalance) throws RpcException {
// 1. 选择服务提供者(通过负载均衡)
Invoker<T> invoker = select(loadbalance, invocation, invokers, null);
try {
// 2. 发起调用
return invoker.invoke(invocation);
} catch (RpcException e) {
// 3. 自定义失败处理(如降级、重试)
return mockInvoker.invoke(invocation); // 降级逻辑
}
}
}
}
- 在
META-INF/dubbo/org.apache.dubbo.rpc.cluster.Cluster文件中注册:
custom=com.xxx.CustomCluster
- 配置使用自定义策略:
cluster="custom"。
四、Dubbo 负载均衡(Load Balancing)
核心原理
负载均衡的目标是将消费者的请求均匀分发到多个服务提供者,避免单点过载。Dubbo 的负载均衡由 LoadBalance 组件实现:
- 消费者发起调用时,
Cluster会获取所有可用的服务提供者列表(Invoker集合); LoadBalance组件根据预设策略,从列表中选择一个最优的Invoker;- 支持基于权重的动态调整(服务提供者可配置权重,权重越高,被选中的概率越大)。
核心接口:org.apache.dubbo.rpc.cluster.LoadBalance,Dubbo 内置 4 种常用实现,支持自定义。
常用负载均衡策略(内置实现)
Dubbo 2.7+ 内置 4 种核心负载均衡策略,配置优先级:方法级 > 接口级 > 全局级:
| 策略名称 | 英文标识 | 核心逻辑 | 适用场景 |
|---|---|---|---|
| 随机权重 | random | 按服务提供者的权重随机选择(默认策略),权重越高,概率越大 | 大多数无状态服务(默认推荐) |
| 轮询权重 | roundrobin | 按权重轮询选择,解决简单轮询的负载不均问题(基于加权轮询算法) | 服务节点性能差异小、无状态服务 |
| 最少活跃调用 | leastactive | 选择「活跃调用数最少」的服务提供者(活跃数 = 当前正在处理的请求数) | 服务节点性能差异大、请求耗时不均的场景 |
| 一致性哈希 | consistenthash | 基于请求参数的哈希值,将同一参数的请求路由到同一服务提供者(支持虚拟节点) | 有状态服务(如会话保持)、缓存服务 |
关键细节:
- 所有策略均支持权重配置(
weight参数,默认 100),权重为 0 表示该节点不参与负载均衡; consistenthash可配置虚拟节点数(hash.nodes=160),减少哈希抖动;leastactive需配合actives参数(服务最大并发数),活跃数统计基于 Dubbo 的线程池。
2万+

被折叠的 条评论
为什么被折叠?



