Dubbo 架构入门:组件、流程、方法、容错机制的通俗讲解

一、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(监控中心)。
  • 实时上报调用次数、成功率、平均耗时、超时次数等核心指标。
  • 监控中心通过统计数据支撑服务治理,比如熔断、限流、性能优化。

方法间关联逻辑

  1. 启动顺序:start → register(Provider 侧)/ subscribe(Consumer 侧)。
  2. 动态更新:register 触发 Registry 数据变更 → notify 同步给 Consumer。
  3. 调用链路: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 组件主导:

  1. 消费者发起调用时,Registry 会返回服务的所有提供者列表(Invoker 集合);
  2. Cluster 会将多个 Invoker 包装成一个集群 Invoker(屏蔽多节点细节);
  3. 当调用失败时,集群 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 扩展自定义:

  1. 实现 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); // 降级逻辑
            }
        }
    }
}
  1. META-INF/dubbo/org.apache.dubbo.rpc.cluster.Cluster 文件中注册:
custom=com.xxx.CustomCluster
  1. 配置使用自定义策略:cluster="custom"

四、Dubbo 负载均衡(Load Balancing)

核心原理

负载均衡的目标是将消费者的请求均匀分发到多个服务提供者,避免单点过载。Dubbo 的负载均衡由 LoadBalance 组件实现:

  1. 消费者发起调用时,Cluster 会获取所有可用的服务提供者列表(Invoker 集合);
  2. LoadBalance 组件根据预设策略,从列表中选择一个最优的 Invoker
  3. 支持基于权重的动态调整(服务提供者可配置权重,权重越高,被选中的概率越大)。

核心接口: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 的线程池。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

TracyCoder123

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值