Golang&Pythonspanner/grpc/hdfs/hbase/spark

grpc协议解析及新语言支持

2018-07-01  本文已影响189人  xin3521

(一)grpc 协议分析。
gRPC 是基于 HTTP/2 协议的,要深刻理解 gRPC,理解下 HTTP/2 是必要的,这里先简单介绍一下 HTTP/2 相关的知识,然后在介绍下 gRPC 是如何基于 HTTP/2 构建的。
HTTP/1.x
HTTP 协议可以算是现阶段 Web 上面最通用的协议了,在之前很长一段时间,很多应用都是基于 HTTP/1.x 协议,HTTP/1.x 协议是一个文本协议,可读性非常好,但其实并不高效,笔者主要碰到过几个问题:
Parser
如果要解析一个完整的 HTTP 请求,首先我们需要能正确的读出 HTTP header。HTTP header 各个 fields 使用 \r\n 分隔,然后跟 body 之间使用 \r\n\r\n 分隔。解析完 header 之后,我们才能从 header 里面的 content-length 拿到 body 的 size,从而读取 body。
这套流程其实并不高效,因为我们需要读取多次,才能将一个完整的 HTTP 请求给解析出来,虽然在代码实现上面,有很多优化方式,譬如:

Length:也就是 Frame 的长度,默认最大长度是 16KB,如果要发送更大的 Frame,需要显示的设置 max frame size。 Type:Frame 的类型,譬如有 DATA,HEADERS,PRIORITY 等。 Flag 和 R:保留位,可以先不管。 Stream Identifier:标识所属的 stream,如果为 0,则表示这个 frame 属于整条连接。 Frame Payload:根据不同 Type 有不同的格式。
可以看到,Frame 的格式定义还是非常的简单,按照官方协议,赞成可以非常方便的写一个出来。
Multiplexing
HTTP/2 通过 stream 支持了连接的多路复用,提高了连接的利用率。Stream 有很多重要特性:

grpc_op ops[6];
ops[0].op = GRPC_OP_SEND_INITIAL_METADATA;
...
ops[1].op = GRPC_OP_SEND_MESSAGE;
...
ops[2].op = GRPC_OP_SEND_CLOSE_FROM_CLIENT;
...
ops[3].op = GRPC_OP_RECV_INITIAL_METADATA;
...
ops[4].op = GRPC_OP_RECV_MESSAGE;
...
ops[5].op = GRPC_OP_RECV_STATUS_ON_CLIENT;

return grpcwrap_call_start_batch(call, ops, tag);
}
用其他语言 封装 core
比如封装 CQ next():
c语言 : grpc_event grpc_completion_queue_next(grpc_completion_queue *cq,
gpr_timespec deadline,
void *reserved);
接着我们看看如何封装 C 的类型。继续以 next() 为例子:
// CQ 指针
grpc_completion_queue *cq;
// grpc_event 结构体
struct grpc_event {
grpc_completion_type type;
int success;
void *tag;
};
上面说过 Core 能异步处理 RPC,那么如何用 其他语言来做更好的封装呢? Futures!它是一个成熟的异步编程库,同时有一个活跃的社区。 Futures 非常适用于 RPC 等一些 IO 操作频繁的场景。Futures 中也有组合子概念,和 Core 中的类似,但是使用上更加方便,也更加好理解。
参考资料:
gRPC open-source universal RPC framework

上一篇下一篇

猜你喜欢

热点阅读