Dubbo 支持的 RPC 通信协议
Dubbo 作为一款 RPC 框架内置了高效的 RPC 通信协议,帮助解决服务间的编码与通信问题,目前支持的协议包括:
- triple,基于 HTTP/1、HTTP/2 的高性能通信协议,100% 兼容 gRPC,支持 Unary、Streming 等通信模式;
- dubbo,基于 TCP 的高性能私有通信协议,缺点是通用性较差,只能在 Dubbo SDK 间使用;
- rest,基于 HTTP+JSON 标准的通信协议,用于发布 REST 风格的 HTTP 服务,网关等路由组件兼容性高;
- 多种生态扩展协议;
以下是几个主要协议的具体信息:
协议名称 | 配置值 | 服务定义方式 | 默认端口 | 传输层协议 | 序列化协议 | 是否默认 |
---|---|---|---|---|---|---|
triple | tri | - Java Interface - Protobuf(IDL) | 50051 | HTTP/1、HTTP/2 | Protobuf Binary、Protobuf JSON | 否 |
dubbo | dubbo | - Java Interface | 20880 | TCP | Hessian、Fastjson2、JSON、JDK、Avro、Kryo 等 | 是 |
rest | rest | - Java Interface + SpringMVC - Java Interface + JAX-RS | 8080 | HTTP/1、HTTP/2 | JSON | 否 |
注意
考虑到对过往版本的兼容性,当前 Dubbo 各个发行版本均默认使用dubbo
通信协议。但对于新用户而言,我们强烈建议在一开始就选用 triple
协议,老用户也尽快参考文档 实现协议的平滑迁移。Triple 协议
通过以下配置启用 triple 协议,默认端口为 50051,如果设置 port: -1
则会随机选取端口(从 50051 自增,直到找到第一个可用端口)。
dubbo:
protocol:
name: tri
port: 50051
服务定义方式
使用 triple 协议时,开发者可以使用 Java Interface
、Protobuf(IDL)
两种方式定义 Dubbo RPC 服务,两种服务定义模式下的协议能力是对等的,仅影响开发者的编程体验,具体选用那种开发模式,取决于使用者的业务背景。
1. Java Interface
即通过声明一个 Java 接口的方式定义服务,我们在快速开始一节中看到的示例即是这种模式,适合于没有跨语言诉求的开发团队,具备学习成本低的优势,Dubbo2 老用户可以零成本切换协议。
服务定义范例:
public interface DemoService {
String sayHello(String name);
}
在这种模式下,序列化方式可以选用 Hessian、JSON、Kryo、JDK、自定义扩展等任意编码协议。在使用体验上,可以说与老版本 dubbo 协议没有任何区别,只需要改一个 protocol 配置项即可,因此对于 dubbo 协议迁移到 triple 也会更平滑。
- 请通过【进阶学习 - 通信协议】查看 java Interface + Triple 协议的具体使用示例。
2. Protobuf(IDL)
使用 Protobuf(IDL) 的方式定义服务,适合于当前或未来有跨语言诉求的开发团队,同一份 IDL 服务可同时用于 Java/Go/Node.js 等多语言微服务开发,劣势是学习成本较高。
syntax = "proto3";
option java_multiple_files = true;
package org.apache.dubbo.springboot.demo.idl;
message GreeterRequest {
string name = 1;
}
message GreeterReply {
string message = 1;
}
service Greeter{
rpc greet(GreeterRequest) returns (GreeterReply);
}
通过 Dubbo 提供的 protoc 编译插件,将以上 IDL 服务定义预编译为相关 stub 代码,其中就包含 Dubbo 需要的 Interface 接口定义,因此在后续编码上区别并不大,只不过相比于前面的用户自定义 Java Interface 模式,这里由插件自动帮我们生成 Interface 定义。
// Generated by dubbo protoc plugin
public interface Greeter extends org.apache.dubbo.rpc.model.DubboStub {
String JAVA_SERVICE_NAME = "org.apache.dubbo.springboot.demo.idl.Greeter";
String SERVICE_NAME = "org.apache.dubbo.springboot.demo.idl.Greeter";
org.apache.dubbo.springboot.demo.idl.GreeterReply greet(org.apache.dubbo.springboot.demo.idl.GreeterRequest request);
// more generated codes here...
}
这种模式支持序列化方式有 Protobuf Binary、Protobuf JSON 两种模式。
- 请通过【进阶学习 - 通信协议】查看 Protobuf (IDL) + Triple 协议的具体使用示例。
HTTP 接入方式
triple 协议支持标准 HTTP 工具的直接访问,因此前端组件如浏览器、网关等接入非常边便捷,同时服务测试也变得更简单。
当服务启动后,可以使用 cURL 命令直接访问:
curl \
--header "Content-Type: application/json" \
--data '["Dubbo"]' \
http://localhost:50052/org.apache.dubbo.springboot.demo.idl.Greeter/greet/
以上默认使用 org.apache.dubbo.springboot.demo.idl.Greeter/greet
这种 HTTP 访问路径,且仅支持 post 方法,如果你想对外发布 REST 风格服务,请参考下文 REST 协议小节。
Streaming 通信模式
Dubbo 协议
通过以下配置启用 dubbo 协议,默认端口为 20880,如果设置 port: -1
则会随机选取端口(从 20880 自增,直到找到第一个可用端口)。
dubbo:
protocol:
name: dubbo
port: 20880
服务定义方式
dubbo 协议支持使用 Java Interface
方式定义 Dubbo RPC 服务,即通过声明一个 Java 接口的方式定义服务。序列化方式可以选用 Hessian、Fastjson2、JSON、Kryo、JDK、自定义扩展等任意编码协议,默认序列化协议为 Fastjson2。
public interface DemoService {
String sayHello(String name);
}
注意
自 3.2.0 版本开始,Dubbo 增加了序列化协议的自动协商机制,如果满足条件 两端都为 Dubbo3 特定版本 + 存在 Fastjson2 相关依赖
,则会自动使用 fastjson2 序列化协议,否则使用 hessian2 协议,协商对用户透明无感。
由于 Dubbo2 默认序列化协议是 hessian2,对于部分有拦截rpc调用payload的场景,比如sidecar等对链路payload有拦截与解析,在升级过程中需留意兼容性问题。
- 关于 dubbo 协议的具体使用示例请参见【进阶学习 - 通信协议】中的 dubbo 协议示例。
HTTP 接入方式
由于 dubbo 协议无法支持 http 流量直接接入,因此需要有一层网关实现前端 http 协议到后端 dubbo 协议的转换过程(http -> dubbo
)。Dubbo 框架提供了 泛化调用
能力,可以让网关在无服务接口定义的情况下对后端服务发起调用。
目前社区有很多开源网关产品支持 http -> dubbo
的,它们大部分都提供了可视化界面配置参数映射(泛化调用),同时还支持包括 Nacos、Zookeeper 等主流的注册中心。
- Higress
- Pixiu
- APISIX
- Shenyu
- Tengine
REST 协议
通过以下配置启用 rest 协议,默认端口为 8080,如果设置 port: -1
则会随机选取端口(从 8080 自增,直到找到第一个可用端口)。
dubbo:
protocol:
name: rest
port: 8080
服务定义方式
目前 rest 协议仅支持 Java Interface
服务定义模式,相比于 dubbo 和 triple 协议,rest 场景下我们需要为 Interface 增加注解,目前支持 Spring MVC、JAX_RS 两种注解。
Spring MVC 服务定义范例:
@RestController
@RequestMapping("/demo")
public interface DemoService {
@GetMapping(value = "/hello")
String sayHello();
}
jAX-RS 服务定义范例:
@RestController
@RequestMapping("/demo")
public interface DemoService {
@GetMapping(value = "/hello")
String sayHello();
}
如果你记得 triple 协议原生支持 cURL 访问,即类似 org.apache.dubbo.springboot.demo.idl.Greeter/greet
的访问模式。通过增加以上注解并将服务同时发布到 triple 协议、rest 协议,可以为 triple 服务额外增加 REST 风格访问支持。
dubbo:
protocols:
- name: rest
port: 8080
- name: triple
port: 50051
更多协议
与 RPC 协议强相关的,Dubbo 支持从多个角度调整 RPC 调用时的行为,比如超时时间、线程池、连接数、负载大小、异步调用、隐式传参等,具体请查看 RPC 框架与 API 中说明。
除此之外,关于 RPC 协议还有以下相关链接可以参考:
- 更多
- 扩展 RPC 协议
- 序列化协议
- RPC 协议使用示例
- triple 协议规范
- dubbo 协议规范
- rest 协议规范