Dubbo 支持的 RPC 通信协议

Dubbo 是一款轻量的 RPC 框架,提供 Java、Go、Node.js、Javascript 等语言支持,帮助开发者构建浏览器、gRPC 兼容的 HTTP API。

Dubbo 作为一款 RPC 框架内置了高效的 RPC 通信协议,帮助解决服务间的编码与通信问题,目前支持的协议包括:

  • triple,基于 HTTP/1、HTTP/2 的高性能通信协议,100% 兼容 gRPC,支持 Unary、Streming 等通信模式;
  • dubbo,基于 TCP 的高性能私有通信协议,缺点是通用性较差,只能在 Dubbo SDK 间使用;
  • rest,基于 HTTP+JSON 标准的通信协议,用于发布 REST 风格的 HTTP 服务,网关等路由组件兼容性高;
  • 多种生态扩展协议

以下是几个主要协议的具体信息:

协议名称配置值服务定义方式默认端口传输层协议序列化协议是否默认
tripletri- Java Interface
- Protobuf(IDL)
50051HTTP/1、HTTP/2Protobuf Binary、Protobuf JSON
dubbodubbo- Java Interface20880TCPHessian、Fastjson2、JSON、JDK、Avro、Kryo 等
restrest- Java Interface + SpringMVC
- Java Interface + JAX-RS
8080HTTP/1、HTTP/2JSON

Triple 协议

通过以下配置启用 triple 协议,默认端口为 50051,如果设置 port: -1 则会随机选取端口(从 50051 自增,直到找到第一个可用端口)。

dubbo:
 protocol:
   name: tri
   port: 50051

服务定义方式

使用 triple 协议时,开发者可以使用 Java InterfaceProtobuf(IDL) 两种方式定义 Dubbo RPC 服务,两种服务定义模式下的协议能力是对等的,仅影响开发者的编程体验,具体选用那种开发模式,取决于使用者的业务背景。

1. Java Interface

即通过声明一个 Java 接口的方式定义服务,我们在快速开始一节中看到的示例即是这种模式,适合于没有跨语言诉求的开发团队,具备学习成本低的优势,Dubbo2 老用户可以零成本切换协议

服务定义范例:

public interface DemoService {
    String sayHello(String name);
}

在这种模式下,序列化方式可以选用 Hessian、JSON、Kryo、JDK、自定义扩展等任意编码协议。在使用体验上,可以说与老版本 dubbo 协议没有任何区别,只需要改一个 protocol 配置项即可,因此对于 dubbo 协议迁移到 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 两种模式。

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);
}
  • 关于 dubbo 协议的具体使用示例请参见【进阶学习 - 通信协议】中的 dubbo 协议示例

HTTP 接入方式

由于 dubbo 协议无法支持 http 流量直接接入,因此需要有一层网关实现前端 http 协议到后端 dubbo 协议的转换过程(http -> dubbo)。Dubbo 框架提供了 泛化调用 能力,可以让网关在无服务接口定义的情况下对后端服务发起调用。

http -> 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
  • 关于 rest 协议的具体使用示例请参见【进阶学习 - 通信协议】中的 rest 协议示例
  • 关于 Dubbo 多协议支持的更多细节请参见【进阶学习 - 通信协议】中的 多协议发布

更多协议

与 RPC 协议强相关的,Dubbo 支持从多个角度调整 RPC 调用时的行为,比如超时时间、线程池、连接数、负载大小、异步调用、隐式传参等,具体请查看 RPC 框架与 API 中说明。

除此之外,关于 RPC 协议还有以下相关链接可以参考:

  • 更多
  • 扩展 RPC 协议
  • 序列化协议
  • RPC 协议使用示例
  • triple 协议规范
  • dubbo 协议规范
  • rest 协议规范

最后修改 December 26, 2023: Update java sdk doc (#2883) (a6d947a45d)