Dubbo 3 配合 Java 接口使用 Triple 协议
大纲
前言
本文将整合 SpringBoot 与 Dubbo 3,并结合 Java 接口(纯 POJO 接口)使用 Triple 协议,使用的注册中心是 Nacos。值得一提的是,本文实现的 RPC 服务可以使用标准 HTTP 工具(比如 Curl + JSON)直接调用。对于期望平滑升级到 Dubbo 3,并且没有多编程语言业务或者不熟悉 Protobuf 的用户而言,使用 Java 接口直接定义服务的模式是最简单的使用 Triple 协议的方式,此模式下 Triple 协议的使用方式与经典 Dubbo 协议(基于 TCP 长连接)是基本一样的。
特别注意
- 基于 Java 接口(纯 POJO 接口)+ Triple 协议实现的 RPC 服务,可以通过标准的 HTTP 工具(比如
curl)直接调用 RPC 服务,缺点是不适合开发多编程语言业务。 - 由于 gRPC 仅支持 Protobuf 模式(使用
.proto文件定义服务),因此基于 Java 接口 + Triple 协议实现的 RPC 服务无法与谷歌官方原生的 gRPC 客户端(协议)互相调用;若需要实现互相调用,可以改为 配合 Protobuf(IDL)使用 Triple 协议。
学习资源
版本对应关系
SpringBoot 与 Dubbo 的版本必须互相匹配,否则不同版本之间可能会存在兼容性问题,最终导致服务无法正常运行。两者的版本对应关系如下:
| Dubbo 分支 | 最新版本 | JDK | SpringBoot | 详细说明 |
|---|---|---|---|---|
| 3.3.x | 3.3.0 | 8, 17, 21 | 2.x、3.x | 生产可用(推荐,长期维护)! 最新 Triple 协议升级,内置 Metrics、Tracing、GraalVM 支持等 |
| 3.2.x | 3.2.10 | 8, 17 | 2.x、3.x | 生产可用(长期维护)! |
| 3.1.x | 3.1.11 | 8, 17 | 2.x、3.x | 仅修复安全漏洞! |
| 3.0.x | 3.0.15 | 8 | 2.x | 停止维护! |
| 2.7.x | 2.7.23 | 8 | 2.x | 停止维护! |
| 2.6.x | 2.6.20 | 6, 7 | - | 停止维护! |
| 2.5.x | 2.5.10 | 6, 7 | - | 停止维护! |
如果仍然使用版本低于 2.7.0 的旧版 Dubbo,请使用以下 Spring Boot 启动器:
| Dubbo Spring Boot Starter | Dubbo | Spring Boot |
|---|---|---|
| 0.2.1.RELEASE | 2.6.5+ | 2.x |
| 0.1.2.RELEASE | 2.6.5+ | 1.x |
Triple 协议介绍
提示
从 Dubbo 3.2 开始,Dubbo 官方已经废弃原有的 gRPC 协议,使用 Triple 协议进行替代。Triple 协议完全兼容 gRPC 协议,更详细的协议介绍请看 这里。
Triple 协议的核心概念
- Triple 协议是 Dubbo 3 引入的新一代 RPC 通信协议,旨在替代经典 Dubbo 协议(基于 TCP 长连接),支持更加现代化、开放的服务互通标准。
- Triple 协议本质上是基于 gRPC/HTTP/2 规范的 RPC 协议,但是它做了兼容性扩展,支持 Dubbo 的接口声明风格,保留了 Dubbo 的生态优势。
- Triple 协议是一个基于 HTTP 传输层协议的 RPC 协议,它完全兼容 gRPC,可运行在 HTTP/1、HTTP/2 之上,并同时结合了 HTTP/2、Protobuf 和 Dubbo 的能力。
Triple 协议的诞生背景
为什么 Dubbo 3 推出 Triple 协议呢?主要原因有以下几个:
- 经典 Dubbo 协议是私有的 TCP 协议,无法与多语言、云原生环境很好兼容。
- 微服务逐步走向云原生 + 多语言 + Service Mesh + 网关接入。
- gRPC 成为业界事实标准,Dubbo 社区需要更开放的通信协议。
Triple 协议的核心特点
| 特点 | 说明 |
|---|---|
| 基于 HTTP/2 | 多路复用、长连接、低延迟 |
| 多语言互操作性 | 兼容 gRPC,支持跨语言调用 |
| IDL 支持灵活 | 可选 Protobuf 或 Java 接口定义(兼容 Dubbo 2 的 API 方式) |
| 支持流式调用 | 实现了 gRPC 的流式通信能力 |
| 安全性更好 | 支持 HTTP/2 的 TLS/SSL |
| 更好的网关兼容性 | 能直接被 Envoy、APISIX 等 API 网关代理 |
| 保留 Dubbo 的服务治理 | 如注册中心、路由、限流、熔断等 |
| 支持零侵入升级 | Dubbo 2 可以平滑过渡到 Triple |
Triple 协议的应用场景
- 多语言 RPC 通信(Java ⇄ Go ⇄ Node)
- 云原生环境(与 Envoy Mesh 兼容)
- 高并发长连接应用(HTTP/2 多路复用)
- 数据流实时传输(流式调用)
- Dubbo 2 平滑升级到 Dubbo 3
Triple 协议发布 REST 服务
Dubbo 3 为 Triple 协议发布 REST 风格的服务提供了内置支持,具体使用方式取决于开发者使用的是基于 Protobuf 的服务定义模式,还是基于 Java 接口的服务定义模式:
- (1)
Java 接口的服务定义模式:通过直接为 Java 接口增加注解,可以发布 REST 风格的服务,目前支持 Spring Web 注解与 JAX-RS 注解。 - (2)
Protobuf 的服务定义模式:通过配合 Protobuf 使用 Triple 协议,使用 IDL 定义服务,并使用 Protobuf 编码业务数据,最后可以选择使用 gRPC-Gateway 发布 REST 风格的服务。
值得一提的是,Protobuf 与 gRPC-Gateway 的简单介绍如下:
- (1)
Protobuf(Protocol Buffers):Google 开发的一种轻量级、高效的数据序列化协议,常用于跨语言、跨平台的数据交换。它类似于 JSON 或 XML,但具有更高的性能和更小的数据体积,适用于网络通信、配置文件、数据存储等场景。 - (2)
gRPC-Gateway:一个基于 Go 语言的开源协议转换工具,它能够将 RESTful 请求(基于 HTTP/JSON)转换为 gRPC 调用(基于 HTTP/2 + Protobuf)。这样,客户端就可以使用普通的 HTTP 请求(如浏览器)来访问 gRPC 服务,而无需专门使用 gRPC 客户端。
提示
若希望 Dubbo 3 使用 Triple 协议 + Java 接口(基于 Spring Web 注解)的服务定义模式来发布 REST 风格的服务,可以看 这里 的教程。
Triple 协议支持的调用模型
| RPC 模式 | 说明 |
|---|---|
| Unary RPC | 单次请求 - 响应 |
| Server Streaming | 服务端流式返回 |
| Client Streaming | 客户端流式请求 |
| Bi-directional Streaming | 双向流式 |
Triple 与经典 Dubbo 协议的区别
| 特性 | Triple(Dubbo 3) | Dubbo 协议(Dubbo 2) |
|---|---|---|
| 传输协议 | HTTP/2 | 自定义 TCP 协议(单连接) |
| 序列化协议 | Protobuf / Hessian2 / JSON | Hessian2(默认) |
| 多语言支持 | 是,天然支持 gRPC 互通 | 较差(主要 Java) |
| 网关支持 | 支持 Envoy、APISIX、Kong | 不兼容 |
| 流式通信 | 支持(Streaming RPC) | 不支持 |
| 扩展性 | 兼容 gRPC 插件生态 | 自定义扩展(Dubbo Filter) |
| 可观测性 | 标准化 Trace、Metrics | 自行扩展 |
| 连接复用 | HTTP/2 多路复用 | 单连接单请求 |
| 协议标准化程度 | 标准协议,开放生态 | 私有协议 |
Triple 协议原理
Triple 协议的序列化机制
Triple 协议的本质:
- 传输层:HTTP/2
- 编解码:
- 默认支持
application/grpc+proto,完全兼容 gRPC 标准 - 兼容 HTTP/JSON 调用(但严格来说,gRPC 标准并没有支持
application/grpc+json,而是 Dubbo 自行扩展了 JSON 兼容功能)
- 默认支持
Triple 接口类型与序列化逻辑:
- 如果是
.proto生成的接口- 完全走 Protobuf 序列化
- 客户端和服务端都用
.proto定义的结构进行 Protobuf 编解码 - 兼容标准 gRPC 协议
- 客户端和服务端都用
- 完全走 Protobuf 序列化
- 如果是 Java 接口(非
.proto生成)- HTTP/JSON 调用(如
curl+application/json):- 完全走 Hessian2Json 或 Jackson 等 JSON 序列化
- 传输层是 HTTP/1.1
- 不会经过 Protobuf 序列化
- HTTP/JSON 调用(如
- 如果是
Triple 协议为什么这样设计:
- Triple 协议本质上是 gRPC 兼容协议
- gRPC 强制要求底层用 Protobuf 编解码
- Dubbo 为兼容老用户,支持「Java 接口直发」
- 如果是 HTTP/JSON 调用,仍保持兼容 JSON(非 Protobuf 序列化)
Triple 协议的序列化机制总结
| 调用方式 | 序列化 | 服务定义模式 |
|---|---|---|
gRPC 标准调用(HTTP/2 + application/grpc+proto) | 直接走 Protobuf 序列化 | 基于 .proto 文件定义服务 |
HTTP/JSON 调用(HTTP/1 + application/json) | 直接走 Hessian2Json 或 Jackson 序列化(不经过 Protobuf 序列化) | 基于 Java 接口(纯 POJO 接口)定义服务 |
Triple 协议的两种调用方式
| 服务定义方式 | 是否支持 HTTP + JSON 调用 | 是否支持 gRPC 客户端(协议)调用 | 是否支持跨编程语言调用 |
|---|---|---|---|
基于 .proto 文件的服务定义 | ❌ 不支持 HTTP + JSON 调用 | ✅ 支持 gRPC 客户端(协议)调用,由于必须用 Protobuf 二进制,通常用 gRPC 调用 | ✅ 支持跨编程语言调用 |
| 基于 Java 接口的服务定义(纯 POJO 接口) | ✅ 支持 HTTP + JSON 调用,内部直接走 Hessian2Json 或 Jackson 序列化(不经过 Protobuf 序列化) | ❌ 不支持 gRPC 客户端(协议)调用,由于 gRPC 仅支持 Protobuf 模式(使用 .proto 文件定义服务),因此 Java 接口 + Triple 协议的模式无法与谷歌官方原生的 gRPC 协议互相调用 | ❌ 不支持跨编程语言调用 |
Dubbo 使用案例
本节将整合 SpringBoot 与 Dubbo 3,并配合 IDL + Protobuf 使用 Triple 协议,使用的注册中心是 Nacos,完整的项目目录结构如图所示。值得一提的是,本教程的内容也适用于 Spring Cloud 项目。
版本说明
| 组件 | 版本 | 说明 |
|---|---|---|
| SpringBoot | 3.4.2 | |
| Dubbo Spring Boot Starter | 3.3.2 | 依赖 Dubbo 3.3.2 |
| Nacos Server | 2.5.0 | Nacos 服务器,作为服务注册中心 |
| JDK | 17 | 支持 JDK 17 及以上版本 |
模块说明
api:抽取出来的公共模块,存放公用的实体类和接口provider:服务提供者,实现api模块中的接口customer:服务消费者,调用服务提供者中的接口
案例代码
API 模块
- 引入依赖
1 | <properties> |
- 定义实体类
1 |
|
- 定义 Java 接口(纯 POJO 接口)
1 | public interface UserService { |
Provider 模块
- 引入依赖
1 | <properties> |
- 接口实现类,
@DubboService注解主要用于暴露服务,使其能够被 Dubbo 框架识别并注册到服务注册中心
1 | import org.apache.dubbo.config.annotation.DubboService; |
- 主启动类
1 |
|
- 配置文件(
application.yml)
1 | server: |
提示
若不希望在 YML 配置文件中指定 dubbo.scan.base-packages 参数,那么可以在主启动类上标注 @EnableDubbo(scanBasePackages = "xxx") 注解或者 @DubboComponentScan(basePackages = "xxx") 注解来替代。
Consumer 模块
- 引入依赖
1 | <properties> |
- 业务测试类,
@DubboReference注解主要用于在服务消费者端引用远程服务提供者的服务
1 | import org.apache.dubbo.config.annotation.DubboReference; |
- 主启动类
1 |
|
- 配置文件(
application.yml)
1 | server: |
提示
若不希望在 YML 配置文件中指定 dubbo.scan.base-packages 参数,那么可以在主启动类上标注 @EnableDubbo(scanBasePackages = "xxx") 注解或者 @DubboComponentScan(basePackages = "xxx") 注解来替代。
测试代码
测试案例一
(1) 启动 Nacos 服务器
(2) 在 IDEA 开发工具内,分别启动 Provider 和 Consumer 模块
(3) 使用 Postman 等工具访问 Consumer 模块的
http://127.0.0.1:9095/system/getUser/1接口,若接口可以正常返回 JSON 响应结果,则说明 Dubbo Triple 协议与 Java 接口正常工作
测试案例二
提示
Dubbo 3 基于 Java 接口(纯 POJO 接口)定义服务,并使用 Triple 协议发布 RPC 服务后,可以通过 HTTP + JSON 的方式直接调用 RPC 服务。
(1) 启动 Nacos 服务器
(2) 在 IDEA 开发工具内,单独启动 Provider 模块
(3) 通过
curl工具直接调用 Provider 模块提供的 RPC 服务,若可以正常返回响应结果,则说明 Dubbo Triple 协议与 Java 接口正常工作
1 | curl \ |
1 | curl \ |
特别注意:为了可以通过 HTTP + JSON 直接调用 RPC 服务,必须注意以下事项
- Dubbo 使用的协议必须指定为
tri - 服务必须是由纯 Java 接口来定义,不能是
.proto文件生成的接口 - 参数格式是 JSON 数组,比如
["Tom", 18],可以传递多个参数(如下述表格所示) - URL 格式:
http://host:port/接口全限定名/方法名,端口必须是 Triple 协议占用的端口(比如50052),并不是 Tomcat 占用的端口
| 参数形式 | JSON 数据 |
|---|---|
| 单个基本类型参数 | ["abc"] |
| 多个基本类型参数 | ["abc", 123] |
| 基本类型 + 对象 | ["admin", {"name":"Tom","age":18}] |
| 单个对象参数 | [{"name":"Tom","age":18}] |
下载代码
- 完整的案例代码可以直接从 GitHub 下载对应章节
dubbo-lesson-04。
Dubbo 实现 REST 服务
HTTP 接入方式
由于经典 Dubbo 协议(基于 TCP 长连接)无法支持 HTTP 流量直接接入,因此需要有一层网关实现前端 HTTP 协议到后端 Dubbo 协议的转换过程(HTTP -> Dubbo)。Dubbo 框架提供了 泛化调用 能力,可以让网关在无服务接口定义的情况下对后端服务发起调用。

目前社区有很多开源网关产品(Higress、Shenyu、APISIX、Tengine 等)支持 HTTP 协议转换为 Dubbo 协议,它们大部分都提供了可视化界面配置参数映射(泛化调用),同时还支持基于 Nacos、Zookeeper 等主流注册中心的自动地址发现,具体请查看 HTTP 网关接入。Dubbo 自 3.3 版本开始 Triple 协议支持基于 Java 接口以 REST 风格发布标准的 HTTP 服务,因此,发布 REST 风格的服务等同于使用 Triple 协议,只不过需要在服务定义(Java 接口)上加入特定的注解(Spring Web 注解或者 JAX-RS 注解)。对于 Dubbo 老版本的 REST 用户配置是 name: rest,用户可以选择将改为 name: tri;即使不修改也没有问题,Dubbo 框架会自动将 REST 转换为 Triple 协议实现。所以说,REST 只是 Triple 协议的一种特殊的发布形式,为了实现 REST 格式发布,需要为服务接口定义增加注解而已。
实现 REST 服务
在上面的案例中,如类似 http://127.0.0.1:50052/user/update 这样的 REST 风格接口更符合前端常用的访问方式,要做到这一点,除了配置网关(如 Higress)的 Rewrite 规则之外,Dubbo 框架还为 Triple 服务暴露 REST 风格的 HTTP 访问路径提供了内置支持,具体使用方式取决于使用的是基于 Protobuf(使用 .proto 文件)的服务定义模式,还是基于 Java 接口的服务定义模式:
- Java 接口模式:通过直接为 Java 接口添加注解,可以发布 REST 风格服务,目前支持 Spring Web 与 JAX-RS 两套注解标准。
- Protobuf 模式:通过使用
grpc-gateway中间件可以发布 REST 风格服务。
Dubbo 3 基于 Java 接口 + Triple 协议 + Spring Web 注解实现 REST 风格接口,只需要在 Java 接口上添加相应注解即可,示例代码如下:
1 | import org.springframework.web.bind.annotation.GetMapping; |
详细教程
Dubbo 基于 Java 接口 + Triple 协议实现 REST 服务的详细教程可以看 这里。
