以服务定义连接两端

gRPC是具体的开源远程过程调用框架,而不是RPC概念本身。服务定义列出可调用的方法、请求和响应类型;常见工具链从.proto文件生成客户端桩与服务端接口,使不同语言编写的程序能依据同一份约定交换消息。服务端仍须实现真正的业务逻辑。

Protocol Buffers是默认的接口描述与消息格式方案,并非协议唯一允许的序列化形式。生成代码处理部分编码和调用工作,却不会把远程调用变成本地函数:网络中断、等待期限和两端独立失效仍然存在。

参考:[1] [4]

一次调用可以包含消息流

gRPC提供四种方法形态:一元调用发送一个请求、取得一个响应;服务端流式调用由一个请求触发多个响应;客户端流式调用先传入多个消息,再取得一个响应;双向流式调用则允许双方分别持续发送。

双向流的两个方向可以独立推进,不必总是一问一答;同一方向的消息顺序会保持,但何时读取、何时返回以及何时结束,仍由应用协议决定。例如持续上传测量值并接收处理结果,可以采用双向流,不能仅因使用HTTP/2就假定业务上自动形成实时订阅。

参考:[1]

HTTP/2状态不等于RPC结果

在标准的HTTP/2映射中,方法名称位于请求路径,消息带有压缩标记和长度前缀,再装入DATA帧。消息边界与HTTP/2帧边界并不要求重合;接收端需要按gRPC消息格式重新识别内容。传输层负责承载字节流,应用方法规定这些消息意味着什么。

正常的gRPC响应可以使用HTTP状态200,同时在尾部元数据的grpc-status中报告调用失败。因此,只统计HTTP成功率会漏掉业务调用层面的错误。标准错误模型包含状态码与可选说明;较丰富的错误细节可以利用额外消息承载,但不同语言库和代理对细节的支持并不完全一致。

参考:[4] [3]

期限与取消不是事务回滚

期限是客户端不愿继续等待的时间点;超时则是允许等待的时长。gRPC通常不自动给调用设置有限期限,应用应根据网络与处理负载明确选择。跨服务调用时,传播剩余时间预算比让每一跳重新获得完整等待时间更能约束总延迟,自动传播是否启用依实现而异。

期限到达后,客户端可能收到DEADLINE_EXCEEDED,而服务端已经完成了修改,只是响应来迟。取消也不会撤销先前发生的变更,服务端自行启动的长任务还需主动检查取消状态并停止。因而重试涉及写入的方法时,应用仍须考虑幂等性、去重和结果查询,不能把“没收到成功”当成“没有执行”。

参考:[2] [1] [4]