应用层rpc 协议 需要关注的一些事

最近, 发现公司的 rpc 框架有些严重bug, 修复后顺便总结下使用一般的 rpc 协议时 需要注意的问题。

  1. 是否压缩

    对于protobuf 和 thrift 来说都有不压缩的,或者仅针对数字的 zigzag。

    而对于 string类型 来说,是不压缩的,如果你的 rpc 的参数与返回大部分的字段都是string 类型的,那么压缩的意义可能并不是很大。

  2. 内存友好

    内存友好体现在, 当有请求过来时,我尽量只需要申请一次空间,或者不需要申请空间

    要实现申请一次空间的话, 那么发送的数据包上就要带上一个 frame 头,用来表示,我这段数据包的大小有多少。
    然后, 我只要申请一次空间, 只有一次 syscall。

  3. 异常处理

    1. 保证即使自身异常也能够告知对方, 免得对方等待直至超时。

      这个 protobuf 和 thrift 都有类似 Exception 类型, 可以实现。

    2. 确定在什么情况下放弃链接。

以下详细解释一些异常的可能性 以及 解决方法。

下面的 c 表示 client, s 表示 server

c -> s

当发请求时, 会有以下可能

c 端

c 编码失败
直接结束

s 端

s 解码失败
server decode 失败后, 应当主动关闭链接。

这种情况,可能是被攻击,可能协议不一致。而且一开始就错误了,也就无法确定连接里面的数据是什么。所以 s 直接关闭链接。

s 关闭连接后, c 将立即收到 connection reset 的错误。

s -> c

s 端

s 编码失败 或者 业务处理失败
s 将response 编码后, 写回连接到 c, 但是, 这时 s 编码失败了。

如果 编码的过程中没有做异常处理, s 将没有数据写会, c 会等待数据到 timeout。

所以, s 对于这种错误应当捕捉, 并且包装成 一个异常结构,返回给 c, 避免 c 的超时。 (ps, 特别当c端的连接是同步的时候,将影响 c 的吞吐量)

c 端

c 读取 s 的返回解码失败
同 s 解码失败,关闭连接, 理由一致
avatar

lelouchcr's blog