gRPC 动机和设计原则
动机
十多年来,谷歌一直使用一种名为 Stubby 的通用 RPC 基础设施,来连接在我们数据中心内和跨数据中心运行的大量微服务。我们的内部系统长期以来都采用着如今流行的微服务架构。拥有统一的跨平台 RPC 基础设施,使得在效率、安全性、可靠性和行为分析方面进行全方位改进成为可能,这对于支持该时期出现的惊人增长至关重要。
Stubby 有许多很棒的功能 - 但是,它不是基于任何标准的,并且与我们的内部基础设施紧密耦合,因此不适合公开发布。随着 SPDY、HTTP/2 和 QUIC 的出现,这些相同的功能中的许多都出现在公共标准中,以及 Stubby 没有提供的其他功能。很明显,现在是时候重新设计 Stubby,以利用这种标准化,并将其适用性扩展到移动、物联网和云用例。
原则和要求
服务而不是对象,消息而不是引用
促进系统之间粗粒度消息交换的微服务设计理念,同时避免分布式对象的陷阱和忽略网络的谬论。
覆盖范围和简单性
该堆栈应在每个流行的开发平台上都可用,并且对于某人来说,很容易为其选择的平台构建。它应该在 CPU 和内存有限的设备上可行。
免费和开放
使所有人都可免费使用基本功能。以开源方式发布所有工件,其许可应有助于采用,而不是阻碍采用。
互操作性和覆盖范围
线路协议必须能够承受在常见互联网基础设施上的传输。
通用和高性能
该堆栈应适用于广泛的用例,同时与特定用例的堆栈相比,性能损失很小。
分层
堆栈的关键方面必须能够独立演变。对线路格式的修订不应破坏应用程序层绑定。
有效载荷无关
不同的服务需要使用不同的消息类型和编码,例如协议缓冲区、JSON、XML 和 Thrift;协议和实现必须允许这样做。同样,对有效载荷压缩的需求因用例和有效载荷类型而异:协议应允许可插拔的压缩机制。
流式传输
存储系统依赖于流式传输和流量控制来表示大型数据集。其他服务,如语音转文本或股票行情,则依赖于流式传输来表示时间相关的消息序列。
阻塞和非阻塞
支持客户端和服务器交换的消息序列的异步和同步处理。这对于在某些平台上扩展和处理流至关重要。
取消和超时
操作可能是昂贵且持久的 - 当客户端表现良好时,取消允许服务器回收资源。当跟踪工作的因果链时,取消可以级联。客户端可以指示调用的超时,这允许服务根据客户端的需求调整其行为。
跛脚鸭
必须允许服务器通过拒绝新请求,同时继续处理正在进行的请求来正常关闭。
流量控制
客户端和服务器之间的计算能力和网络容量通常是不平衡的。流量控制允许更好的缓冲区管理,并提供防止过度活跃的对等方造成的 DOS 攻击的保护。
可插拔
线路协议只是功能性 API 基础设施的一部分。大型分布式系统需要安全性、健康检查、负载均衡和故障转移、监控、跟踪、日志记录等等。实现应提供扩展点,以允许插入这些功能,并在有用时提供默认实现。
扩展即 API
需要在服务之间协作的扩展应尽可能倾向于使用 API 而不是协议扩展。这种类型的扩展可能包括健康检查、服务自检、负载监控和负载均衡分配。
元数据交换
诸如身份验证或跟踪之类的常见横切关注点依赖于数据的交换,而这些数据不是服务声明接口的一部分。部署依赖于以与服务公开的各个 API 不同的速率演变这些功能的能力。
标准化状态码
客户端通常以有限的方式响应 API 调用返回的错误。应约束状态代码命名空间,以使这些错误处理决策更加清晰。如果需要更丰富的特定于域的状态,则可以使用元数据交换机制来提供。