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