Skip to content

RPC协议

cyshi edited this page Nov 17, 2016 · 1 revision

本文档包括:

  • 消息整体结构
  • RpcMessageHeader
  • RpcMeta
  • Data
  • 协议扩展

消息整体结构

Rpc的完整消息由三部分构成:| RpcMessageHeader | RpcMeta | Data |

关于Rpc消息:

  • Rpc是Request/Response模式的,即client端发送一个Request消息,server端收到请求并进行处理,处理完成后回复一个Response消息。一次请求和回复,构成一次完整的Rpc调用。
  • 连接一旦建立以后,便以消息为单位发送数据。一个消息必须完整发送,相邻消息的字节首尾相连,不能有额外数据。
  • 一次Rpc调用的请求和回复必须在一个连接通道(socket)上完成,但Request消息和Response消息的发送顺序不用保持一致,因为在消息中包含有特殊的sequence_id(该id保证连接唯一),可以对属于一个Rpc调用的Request消息和Response消息进行匹配。

RpcMessageHeader

每个Rpc消息都有一个固定长度的消息头,RpcMessageHeader结构体参考源文件sofa/pbrpc/rpc_message_header.h,定义如下:

// total 24 bytes
struct RpcMessageHeader {
    union {
        char    magic_str[4];
        uint32  magic_str_value;
    };                    // 4 bytes
    int32   meta_size;    // 4 bytes
    int64   data_size;    // 8 bytes
    int64   message_size; // 8 bytes: message_size = meta_size + data_size
};

空间大小:共24字节。

序列化方式:struct直接拷贝,小端方式。

各字段意义

属性名 字节数 意义
magic_str 4 魔术字符串“SOFA”
meta_size 4 RpcMeta的数据总长度。RpcMeta是protobuf格式的Message。
data_size 8 Data的数据总长度。Data是protobuf格式的Request Message或者Response Message。
message_size 8 message_size = meta_size + data_size。message_size实际为冗余信息,主要用作meta_size和data_size的一致性检查。

RpcMeta

RpcMeta是一个protobuf结构,其定义参见源文件sofa/pbrpc/rpc_meta.proto

空间大小:protobuf序列化后的大小,与具体内容相关。

序列化方式:使用protobuf的二进制序列化。

各字段意义

属性名 字节数 是否可选 意义
type enum 表明该消息是Request还是Response。
sequence_id uint64 消息的序号,用于匹配一次Rpc调用的Request和Response消息。
method string 仅用于Request消息,记录请求方法的全名,譬如“test.HelloService.GreetMethod”。
failed bool 仅用于Response消息,表示请求是否失败。
error_code int32 仅用于Response消息,在请示失败时记录错误码,该错误码由用户自己定义。
reason string 仅用于Response消息,在请示失败时记录错误信息,通常为可读字符串,可用于打印日志。
compress_type CompressType 可用于Request或者Response。如果设置,表示该消息的Data数据的压缩方式。
expected_response_compress_type CompressType 仅用于Request消息。如果设置,表示client端希望server端返回的Response消息中Data数据的压缩方式。这仅仅是一个提示,server端可以遵守也可以不遵守,实际返回的数据的压缩方式还是由Response的RpcMeta中的“compress_type”字段决定。

Data

Data是消息中的真正有效数据载体。Protobuf的RPC框架规定了统一的调用格式:每个方法有且只能有一个Message类型的传入参数,有且只能有一个Message类型的传出参数。譬如:

service EchoServer {
    rpc Echo(EchoRequest) returns(EchoResponse);
}
  • 对于Request消息,Data数据是传入参数Message的序列化数据。
  • 对于Response消息,Data数据是传出参数Message的序列化数据。如果Response的RpcMeta中failed字段为true,则Data数据为空。
  • 如果使用压缩,则将Message的序列化数据按照特定的压缩格式进行压缩,并在RpcMeta的“compress_type”字段中记录所使用的压缩方式。

空间大小:protobuf序列化后的大小,与具体内容相关。

序列化方式:使用protobuf的二进制序列化。

协议扩展

协议的扩展主要依赖于protobuf的Message的扩展兼容特性。由于RpcMeta是一个protobuf的Message,因此可以根据需要进行扩展。需要注意的是,RpcMeta中新增的字段必须是optional的,否则无法兼容。

譬如RpcMeta的“compress_type”和“expected_response_compress_type”这两个字段,就是为了支持压缩而后来扩展的。

Clone this wiki locally