客户端与服务端的通信需要协商一些内容,例如 HTTP 报文,分为 header 和 body 两部分,body 的格式和长度通过 header 中的 Content-Type
和 Content-Length
指定,服务端通过解析 header 就能够知道如何从 body 中读取需要的信息。对于 RPC 协议来说,这部分协商是需要自主设计的。为了提升性能,一般在报文的最开始会规划固定的字节,来协商相关的信息。比如第 1 个字节用来表示序列化方式,第 2 个字节表示压缩方式,第 3-6 字节表示 header 的长度,7-10 字节表示 body 的长度。
对于 GeeRPC 来说,目前需要协商的唯一一项内容是消息的编解码方式。我们将这部分信息放到结构体 Option
中承载。目前,已经进入到服务端的实现阶段了。
const MagicNumber = 0x3bef5c
type Option struct {
MagicNumber int
CodecType codec.Type
}
var DefaultOption = &Option{
MagicNumber: MagicNumber,
CodecType: codec.GobType,
}
一般来说,涉及协议协商的这部分信息,需要设计固定的字节来传输的。但是为了实现上更简单,GeeRPC 客户端固定采用 JSON 编码 Option
,后续的 header 和 body 的编码方式由 Option
中的 CodecType
指定,服务端首先使用 JSON 解码 Option
,然后通过 Option
的 CodecType
解码剩余的内容。即报文将以这样的形式发送:
1 2 |
| Option{MagicNumber: xxx, CodecType: xxx} | Header{ServiceMethod …} | Body interface{} | | <------ 固定 JSON 编码 ------> | <------- 编码方式由 CodecType 决定 ------>|| |
---|---|
在一次连接中,Option 固定在报文的最开始,Header 和 Body 可以有多个,即报文可能是这样的。 |
1 | | Option | Header1 | Body1 | Header2 | Body2 | … |
---|