本文共 1392 字,大约阅读时间需要 4 分钟。
gRPC定义了四种不同的RPC类型,刚开始接触时可能会感到困惑:这些RPC到底有什么不同?为什么要区分这么多?在没有深入理解源码之前,我也曾疑惑这些RPC背后是否真的有不同的实现机制。经过阅读源码后,我逐渐发现这四种RPC类型在底层实现上本质上并无差异,它们的区别仅在于接口的调用细节。
一元RPC可以理解为最简单的RPC类型。客户端发送一个请求,服务端返回一个响应,与普通函数调用非常类似。其 protobuf 定义格式如下:
rpc SayHello(HelloRequest) returns (HelloResponse);
客户端流式RPC允许客户端发送一连串请求,完成后等待服务器处理并返回一个响应。gRPC保证了同一stream中的请求按发送顺序处理。通过protobuf定义可以看出请求参数中多了一个stream占位符:
rpc LotsOfGreetings(stream HelloRequest) returns (HelloResponse);
服务端流式RPC与客户端流式RPC相反,服务端会发送多个响应给客户端。同样,gRPC保证了同一stream上的消息传输顺序。其定义格式如下:
rpc LotsOfReplies(HelloRequest) returns (stream HelloResponse);
双向流式RPC是最复杂的类型,允许客户端和服务端都能发送多条消息。两端的消息传输顺序独立且互不影响。典型场景如聊天程序等双向通信场景。其定义格式为:
rpc BidiHello(stream HelloRequest) returns (stream HelloResponse);
从流程图可以看出,这四种RPC类型在底层实现上并无本质区别。它们都建立在传输层之上,通过传输层读取数据进行处理。具体差异主要体现在客户端和服务端在发送end_stream标记时的方式:
HTTP/2协议中,end_stream标志用于表示当前帧是否为最后一个帧。如果该标志位为1,则表示当前帧为最后一个帧。
在实际业务开发中,通常只使用一元RPC。如果需要流式通信,根据具体需求选择客户端流式或服务端流式RPC。目前尚未遇到需要双向流式RPC的场景,但这并不意味着其用途不广。双向流式RPC适用于需要双向通信的场景,如实时聊天或数据推送等。
通过对比这四种RPC类型,我们可以看出它们在底层实现上没有本质区别。选择哪种类型取决于具体的业务需求和场景。对于日常开发,通常只需要使用一元RPC即可满足需求。如需流式通信,可以根据具体需求选择合适的类型。
以上内容基于gRPC-Go 1.54.0-dev版本的代码分析,具体实现细节可参考官方文档或源码。
转载地址:http://xbgfk.baihongyu.com/