Apache Dubbo

技术栈
工具链
微服务RPC服务治理远程调用阿里云

概览

Apache Dubbo

Apache Dubbo 是阿里巴巴开源的一款高性能、轻量级的 Java RPC 框架,也是国内最流行的微服务治理框架之一。它提供面向接口的远程方法调用、智能负载均衡、服务自动注册发现、流量治理等能力。

是什么

Dubbo = RPC + 注册中心 + 服务治理。其核心是透明的远程方法调用(就像调用本地方法一样调用远程服务),通过注册中心实现服务自动发现。

解决什么问题

  • 服务间高效通信:比 HTTP REST 更高性能的二进制 RPC 协议
  • 服务治理:负载均衡、超时重试、灰度发布、流量路由
  • 异构系统互通:支持 Java/Go/Rust/Node.js 多语言
  • 协议无关:dubbo:// / tri:// (gRPC) / rest:// 多种协议

关键特性

  • Triple 协议:基于 HTTP/2 + Protobuf,兼容 gRPC 生态
  • 多注册中心:Nacos / ZooKeeper / Consul / Redis / Etcd
  • 多协议:dubbo、tri(gRPC)、rest、hessian、thrift
  • 流量治理:标签路由、条件路由、灰度发布、自适应负载均衡
  • 可观测性:内置 Metrics、Tracing、Logging
  • Spring Boot 3 原生支持:通过 dubbo-spring-boot-starter

安装

Apache Dubbo 安装与初始化

1. 环境准备

要求 说明
JDK JDK 8+(推荐 JDK 17+)
Maven 3.6+ / Gradle 7+
注册中心 Nacos 2.x+ / ZooKeeper 3.4+ / Redis(至少一个)
端口 默认 20880(Dubbo 协议)、50051(Triple/gRPC)

2. 安装命令

Maven 依赖

<!-- Spring Boot 3 + Dubbo 3 -->
<dependency>
    <groupId>org.apache.dubbo</groupId>
    <artifactId>dubbo-spring-boot-starter</artifactId>
    <version>3.3.0</version>
</dependency>

<!-- 注册中心:Nacos(推荐) -->
<dependency>
    <groupId>org.apache.dubbo</groupId>
    <artifactId>dubbo-registry-nacos</artifactId>
    <version>3.3.0</version>
</dependency>

<!-- Triple 协议支持(gRPC 兼容) -->
<dependency>
    <groupId>org.apache.dubbo</groupId>
    <artifactId>dubbo-rpc-triple</artifactId>
    <version>3.3.0</version>
</dependency>

最小配置(application.yml)

dubbo:
  application:
    name: demo-provider
  registry:
    address: nacos://localhost:8848
  protocol:
    name: dubbo
    port: 20880
  provider:
    timeout: 3000
    retries: 2

验证版本

# 查看 Dubbo 版本
mvn dependency:tree | grep dubbo
# org.apache.dubbo:dubbo:jar:3.3.0

3. 常见安装问题

问题 解决方案
No provider available 检查注册中心是否启动,provider 是否成功注册;查看 Nacos 控制台
端口冲突 20880 修改 dubbo.protocol.port 或设置 dubbo.protocol.port=-1 自动分配
序列化异常 Dubbo 3 默认使用 Hessian2,确保 DTO 实现 Serializable
Spring Boot 3 兼容 使用 Dubbo 3.2+,Spring Boot 3.0+
消费者调用超时 配置 dubbo.consumer.timeout,或方法级别 @DubboReference(timeout=5000)
Nacos 2.x 无法注册 确认 Nacos gRPC 端口(9848/9849)开放;Nacos 2.x 要求 Dubbo 3.x
Triple 协议不生效 配置 dubbo.protocol.name=tri,确保依赖 dubbo-rpc-triple

示例

目标

演示 Dubbo + Spring Boot + Nacos 的完整 RPC 调用链路:定义 API → 提供者实现 → 消费者调用。

完整代码

项目结构

dubbo-demo/
├── api/                    # 公共 API 模块
│   └── GreetingService.java
├── provider/               # 服务提供者
│   └── application.yml
│   └── ProviderApplication.java
│   └── GreetingServiceImpl.java
└── consumer/               # 服务消费者
    └── application.yml
    └── ConsumerApplication.java
    └── GreetingController.java

1. API 模块(api/GreetingService.java)

package com.example.api;

public interface GreetingService {
    String sayHello(String name);
    GreetingResponse greet(GreetingRequest request);
}
package com.example.api;

import java.io.Serializable;

public class GreetingRequest implements Serializable {
    private String name;
    private String language;

    public GreetingRequest() {}
    public GreetingRequest(String name, String language) {
        this.name = name;
        this.language = language;
    }
    // getters & setters ...
}

public class GreetingResponse implements Serializable {
    private String message;
    private long timestamp;

    public GreetingResponse() {}
    public GreetingResponse(String message, long timestamp) {
        this.message = message;
        this.timestamp = timestamp;
    }
    // getters & setters ...
}

2. 服务提供者

provider/application.yml

server:
  port: 8081
dubbo:
  application:
    name: demo-provider
  registry:
    address: nacos://localhost:8848
  protocol:
    name: dubbo
    port: 20880
  provider:
    timeout: 3000
    retries: 0
    loadbalance: roundrobin

provider/GreetingServiceImpl.java

package com.example.provider;

import com.example.api.GreetingRequest;
import com.example.api.GreetingResponse;
import com.example.api.GreetingService;
import org.apache.dubbo.config.annotation.DubboService;

@DubboService(version = "1.0.0", group = "demo")
public class GreetingServiceImpl implements GreetingService {

    @Override
    public String sayHello(String name) {
        return "Hello, " + name + "! (from Dubbo Provider)";
    }

    @Override
    public GreetingResponse greet(GreetingRequest request) {
        String msg = switch (request.getLanguage()) {
            case "zh" -> "你好, " + request.getName();
            case "ja" -> "こんにちは, " + request.getName();
            default -> "Hello, " + request.getName();
        };
        return new GreetingResponse(msg, System.currentTimeMillis());
    }
}

provider/ProviderApplication.java

package com.example.provider;

import org.apache.dubbo.config.spring.context.annotation.EnableDubbo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
@EnableDubbo
public class ProviderApplication {
    public static void main(String[] args) {
        SpringApplication.run(ProviderApplication.class, args);
    }
}

3. 服务消费者

consumer/application.yml

server:
  port: 8082
dubbo:
  application:
    name: demo-consumer
  registry:
    address: nacos://localhost:8848
  consumer:
    timeout: 3000
    check: false  # 启动时不检查提供者

consumer/GreetingController.java

package com.example.consumer;

import com.example.api.GreetingRequest;
import com.example.api.GreetingResponse;
import com.example.api.GreetingService;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/api")
public class GreetingController {

    @DubboReference(version = "1.0.0", group = "demo", timeout = 5000)
    private GreetingService greetingService;

    @GetMapping("/hello")
    public String hello(@RequestParam(defaultValue = "World") String name) {
        return greetingService.sayHello(name);
    }

    @GetMapping("/greet")
    public GreetingResponse greet(@RequestParam String name, @RequestParam String lang) {
        return greetingService.greet(new GreetingRequest(name, lang));
    }
}

consumer/ConsumerApplication.java

package com.example.consumer;

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) {
        SpringApplication.run(ConsumerApplication.class, args);
    }
}

运行步骤

# 1. 启动 Nacos
cd nacos/bin &;& sh startup.sh -m standalone

# 2. 启动 Provider
cd provider &;& mvn spring-boot:run

# 3. 启动 Consumer
cd consumer &;& mvn spring-boot:run

# 4. 测试 RPC 调用
curl "http://localhost:8082/api/hello?name=Alice"
# Hello, Alice! (from Dubbo Provider)

curl "http://localhost:8082/api/greet?name=张三&lang=zh"
# {"message":"你好, 张三","timestamp":1716500000000}

# 5. Nacos 控制台查看服务列表
# http://localhost:8848/nacos → 服务管理 → 服务列表

预期输出

Provider 启动日志:
  [DUBBO] DubboBootstrap started

Consumer 调用:
  Hello, Alice! (from Dubbo Provider)
  {"message":"你好, 张三","timestamp":1716500000000}

Nacos 服务列表:
  demo-provider → 1 个健康实例 (192.168.1.x:20880)
  demo-consumer → 1 个健康实例

关键点

  • @DubboService 暴露服务,@DubboReference 引用远程服务
  • versiongroup 用于服务隔离和灰度发布
  • 接口定义在独立 api 模块,provider 和 consumer 共享
  • Dubbo 默认注册到 /dubbo 路径下,与 Spring Cloud / 隔离

教程

前言

RPC(Remote Procedure Call)是微服务通信的基石。与 REST HTTP 不同,RPC 让你像调用本地方法一样调用远程服务。Dubbo 是 Java 生态中最成熟的 RPC 框架,承载着双十一、12306 等超大规模流量。


第一章:Dubbo 架构总览

1.1 核心角色

┌──────────┐  注册/订阅   ┌──────────────┐
│ Provider │◄──────────→│ Registry      │
└────┬─────┘             │ (Nacos/ZK)    │
     │                   └──────┬────────┘
     │ RPC 调用                 │ 发现地址
     ▼                          ▼
┌──────────┐              ┌──────────┐
│ Consumer │──RPC 调用──→│ Provider │
└──────────┘              └──────────┘

Monitor ←─── 统计信息(异步上报)

1.2 调用链路

Consumer 调用 GreetingService.sayHello("Alice")
  → 1. 从 Registry 获取 Provider 地址列表
  → 2. LoadBalance 选择一台 Provider
  → 3. 序列化请求参数(Hessian2 / Protobuf)
  → 4. 通过 Netty 发送二进制数据
  → 5. Provider 反序列化 → 执行 → 序列化结果返回
  → 6. Consumer 收到响应 → 反序列化 → 返回给调用方

第二章:Dubbo 3 新特性

2.1 Triple 协议(HTTP/2 + Protobuf)

Dubbo 2 时代:
  协议: dubbo://(私有协议,非标准)
  序列化: Hessian2
  穿透网关: 需要协议转换

Dubbo 3 时代:
  协议: tri://(基于 HTTP/2,兼容 gRPC)
  序列化: Protobuf(推荐)/ JSON
  穿透网关: 原生 HTTP/2,Envoy/网关直接转发

2.2 应用级服务发现

Dubbo 2: 接口级注册(N 个接口注册 N 条)
   /dubbo/com.example.GreetingService/providers
   /dubbo/com.example.OrderService/providers
   /dubbo/com.example.PaymentService/providers

Dubbo 3: 应用级注册(一个应用注册 1 条)
   /dubbo/demo-provider/instances
   → 大幅减轻注册中心压力

2.3 流量路由与灰度发布

# 标签路由:将流量路由到特定实例
dubbo:
  provider:
    tag: v2  # 只接收 tag=v2 的流量
// 消费者指定路由标签
RpcContext.getClientAttachment().setAttachment("dubbo.tag", "v2");

2.4 自适应负载均衡

Dubbo 3.2+ 引入 P2C(Pick Two Choose One)算法,根据实例实际负载动态选择,而非简单的轮询/随机。


第三章:Dubbo 协议对比

协议 传输层 序列化 适用场景 性能
dubbo:// TCP (Netty) Hessian2 内部 RPC(默认) ⭐⭐⭐⭐
tri:// HTTP/2 Protobuf 跨语言/网关 ⭐⭐⭐⭐⭐
rest:// HTTP JSON 对外开放 API ⭐⭐⭐
grpc:// HTTP/2 Protobuf gRPC 生态 ⭐⭐⭐⭐⭐
redis:// TCP JSON 轻量级 ⭐⭐

第四章:Dubbo vs Spring Cloud vs gRPC

维度 Dubbo Spring Cloud (Feign) gRPC
通信协议 TCP 二进制 HTTP/1.1 + JSON HTTP/2 + Protobuf
性能
跨语言 中等(Go/Rust) 天然 HTTP 原生
服务治理 ✅ 强大 ✅ 中等 ❌ 需额外组件
网关友好 Tri 协议 ✅
Spring 集成 ✅ 原生 ✅ 原生 ✅ spring-grpc
学习曲线 中高
国内生态 ⭐⭐⭐⭐⭐ ⭐⭐⭐ ⭐⭐

第五章:性能调优要点

5.1 线程模型

dubbo:
  protocol:
    name: dubbo
    # I/O 线程池
    iothreads: 4
    # 业务线程池(默认 200)
    threads: 200

5.2 序列化选择

# 高性能场景:Protobuf
dubbo:
  provider:
    serialization: protobuf

# 兼容性优先:Hessian2(默认)
dubbo:
  provider:
    serialization: hessian2

5.3 连接管理

dubbo:
  consumer:
    connections: 1       # 对每个 Provider 的连接数
    actives: 0           # 并发限制(0=不限制)
    actives: 100         # 每服务每消费者最大并发

思考题

  1. Dubbo 3 为什么要从接口级注册改为应用级注册?解决了什么问题?
  2. Triple 协议为什么要基于 HTTP/2?相比 dubbo 协议的 TCP 长连接有什么优势和劣势?
  3. 在 Dubbo 中,超时(timeout)和重试(retries)应该怎么配合设置?设置不当会引发什么"雪崩"?
  4. Dubbo 的 Mock 功能(本地伪装)能解决什么问题?它在生产环境中有哪些实际用途?

下一步

  • 学习 Dubbo + Sentinel 实现限流熔断
  • 学习 Dubbo + Seata 实现分布式事务
  • 学习 Dubbo Mesh(Proxyless Service Mesh)

参考资料

暂无参考文献