-
Notifications
You must be signed in to change notification settings - Fork 654
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消息进行匹配。
每个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是一个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是消息中的真正有效数据载体。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”这两个字段,就是为了支持压缩而后来扩展的。