构建 API 是现代工程中开发人员的最重要任务之一。这些 API 允许不同的系统进行通信和数据交换。虽然 REST 多年来一直是实现 API 的事实标准,但今天也有新兴的标准,如 gRPC 和 GraphQL。
什么是 API?
“应用程序编程接口”(API)是各种软件服务之间的通信渠道。传输请求和响应的应用程序分别称为客户端和服务器。API 是一个外部软件组件,使程序功能可供其他程序使用。
在下面的蜜蜂 🐝 插图中,花朵充当服务器,蜂巢充当客户端,蜜蜂提供通信手段(REST API 请求)。
什么是 API?(图片来源:Rapid API)
存在不同的 API 架构或协议,如 REST、gRPC 和 GraphQL。
为什么 gRPC 很重要?
gRPC 是由 Google 开发的高性能、开源、通用远程过程调用(RPC)框架。它使用 Protocol Buffers (protobuf) 作为其接口定义语言。协议缓冲区是一种非常有效和快速的网络数据序列化方式。这项技术使用 HTTP 2.0 协议 实现了 RPC API;然而,服务器和 API 开发者都无法访问 HTTP。它遵循 客户端-响应通信模型,由于 gRPC 能够接收来自多个客户端的多个请求并同时处理它们,因此支持双向通信和流媒体。然而,gRPC 在浏览器支持方面仍然 相当有限。
如前所述,gRPC 默认使用 Protocol Buffers 来序列化有效载荷数据。Protocol Buffers 是紧凑的二进制序列化格式,用于结构化数据。它们使用在 .proto 文件中定义的模式,允许在不同语言之间进行高效的编码和解码。它们提供了比传统的 JSON 或 XML 更小的尺寸和更快的处理速度等优势。
gRPC 的优点:
- 速度:由于 HTTP/2,gRPC 比 HTTP/1.1 上的 REST 更快、更高效。
- 多语言支持:提供工具在多种语言中生成客户端和服务器代码。
- 流媒体: 支持双向流媒体,允许更互动的实时通信。
- 截止时间/超时: 内置支持确保请求不会挂起。它自动解决重试、网络问题等。
- 生态系统: 支持身份验证、负载均衡等。
gRPC 的缺点:
- 复杂: 您必须了解 Protocol Buffers 和 gRPC API。还必须预先定义模式。
- 浏览器支持有限: 由于依赖 HTTP/2,原生浏览器支持有限。
- 工具: 虽然在增长,但 gRPC 工具的成熟度不如 REST。您可以使用 gRPCurl 或 Postman 来测试这些 API。
- 不可读性: 由于它们是二进制的,它们难以调试,就像您可以使用基于文本的格式(如 XML 或 JSON)那样。
gRPC
什么是 Protocol Buffers?
Protocol Buffers,通常缩写为 Protobuf,是 Google 在 2008 年设计的一种序列化结构化数据的方法。与 XML 或 JSON 类似,它们更精简、更快,因为它们是二进制的,使它们成为与服务器通信或高效存储数据的应用程序的首选。
使用 Protocol Buffers 进行数据序列化涉及几个步骤:
- 定义数据结构:您从在 .proto 文件中定义数据结构开始。这包括指定数据类型(整数、字符串、布尔值、自定义类型等)及其字段编号。
- 生成源代码:使用 Protocol Buffers 编译器(protoc)从文件中生成您所需语言的源代码。编译器可以为多种语言生成代码,包括 Java、C++、Python 等。
- 生成可执行包:可执行包也是与 Protobuf 代码生成的源文件一起生成和部署的。在运行时,消息以二进制格式序列化和压缩。
- 反序列化: 当接收方收到序列化的数据流时,他们可以使用生成的类轻松地将其转换回结构化格式。
什么是 REST API?
REST(Representational State Transfer,表述性状态传递)不是一个框架或库,而是一种用于构建 Web 服务和 API 的架构风格。在 REST 中,一切都是 由唯一 URL 标识的资源,这些资源使用 HTTP 方法(如 GET(检索资源)、POST(创建新资源)、PUT 或 PATCH(更新资源)和 DELETE(移除资源))进行操作。
客户端到服务器的每个请求都必须包含理解和完成请求所需的所有信息。服务器不存储请求之间的客户端上下文,简化了设计并提高了可伸缩性。客户端和服务器的 HTTP 请求和响应体携带 JSON 或 XML 表示 资源的状态。
在他的 博士论文中,计算机科学家 Roy Fielding 在 2000 年介绍并定义了表述性状态传递。 REST API 的好处:
- 简单性: 使用标准 HTTP 方法和常见数据格式使 REST API 易于理解和实现。
- 互操作性: REST API 促进了互操作性,因为不同的应用程序可以无缝交互,无论使用的是哪种编程语言或平台。
- 可伸缩性: REST API 的无状态性质允许轻松扩展以处理大量请求。
- 灵活性: 由于其多功能设计原则,REST API 可以适应各种用例。
REST API 的缺点:
- 无状态性: REST 依赖于无状态事务,这意味着每个请求都必须独立完成所有信息。对于需要在多个请求之间维护状态的工作流程(如电子商务网站上的购物车)来说,这可能很麻烦。
- 有效载荷大小有限: REST 中的数据传输通常通过 JSON 或 XML 有效载荷进行,如果您处理复杂数据或多个查询,这可能会变得相当大。这可能导致性能问题。
- 可发现性不足: REST API 本身并不容易让用户理解其功能或如何与之交互,这可能会为新用户增加复杂性。
- 复杂查询的性能: 对于从较大资源中检索特定数据点,REST 可能不是理想选择。其他选项,如 GraphQL,在这种情况下可能更有效。
REST 定义了一个 API 应该遵循的 六个架构约束,以被认为是真正的 RESTful:
(1) 客户端-服务器: 这种关注点的分离将客户端(使用 API 的应用程序)与服务器(提供 API 的应用程序)分开。客户端发起请求,服务器处理并发送响应。
(2) 无状态: 客户端到服务器的每个请求都必须包含理解请求所需的所有信息。服务器不存储有关客户端的任何上下文。这简化了通信并提高了可伸缩性。
(3) 统一接口: 此约束定义了一组规则,规定客户端如何与服务器交互。这些规则包括:
- 基于资源: API 暴露客户端可以交互的资源。URL 标识资源。
- 标准方法: 客户端使用标准 HTTP 方法(GET、POST、PUT、DELETE)对资源进行操作。
- 表示: 客户端和服务器之间的数据以 JSON 或 XML 等标准格式交换。
(4) 可缓存: 客户端可以将服务器响应标记为可缓存。这允许客户端本地存储频繁访问的数据,减轻服务器负载并提高性能。
(5) 分层系统: 架构可能包括客户端和服务器之间的多个层次(代理、缓存、负载均衡器)。这些层可以提高性能、安全性和可伸缩性。
(6) 按需代码(可选): 虽然不是严格必需的,但 RESTful API 可以选择性地将可执行代码传输给客户端。客户端可以使用此代码扩展其功能或本地处理数据。
REST 架构约束
REST API 调用的一个例子 是当我们想要获取 ID 为 500 的用户信息时,使用 curl 命令行工具为 https://api.example.com 地址上的 API 发出的请求:curl -X GET https://api.example.com/users/500 -H "Accept: application/json"。最后一部分(Accept: application/json)是一个头部,表明客户端期望以 JSON 格式接收数据。响应将是 JSON 格式的结果,200 将是响应状态码。
REST API 架构
即使在性能至关重要时 REST 不是最佳选择,我们仍然可以在这里做一些事情,如 缓存、分页、有效载荷压缩 等。
什么是 GraphQL?
GraphQL 是一种用于 API 的查询语言,由 Meta 在 2015 年发布并开源。现在由 GraphQL 基金会 监督。GraphQL 是一个服务器端运行时环境,使客户端能够从 API 请求所需的数据。与传统的 REST API 不同,后者通常需要多个请求来获取不同的数据片段,GraphQL 允许您在单个请求中指定所需的所有数据。GraphQL 规范在 2015 年开源。
因为 GraphQL 在向 API 发送查询时不会过度或不足地获取结果,它保证了使用 GraphQL 构建的应用程序是 可伸缩、快速和稳定 的。它还允许将多个操作组合成单个 HTTP 请求。
GraphQL API 按照 类型和字段 组织,而不是端点。使用 GraphQL Schema Definition Language (SDL),您将数据定义为模式。这个模式作为客户端和服务器之间的契约,详细说明了可以进行哪些查询、可以获取哪些类型的数据以及响应将是什么样子。
GraphQL 的好处:
- 高效的数据获取: 您只请求确切需要的数据,消除了 REST 可能发生的过度获取或不足获取的问题。这可以显著提高性能,尤其是对于复杂的数据模型。
- 灵活和声明性: GraphQL 使用定义可用数据及其访问方式的模式。这个模式允许开发人员编写清晰、简洁的查询,指定他们确切的数据需求。
- 单个请求用于多个资源: 与 REST 不同,后者需要多个 API 调用来从不同端点获取数据,GraphQL 允许将查询组合成单个请求以提高效率。
- 版本控制和向后兼容性: 可以通过版本控制实现 GraphQL 模式更改,确保现有客户端不受影响,同时允许未来增长。
GraphQL 的缺点:
- 查询结构的复杂性: 虽然灵活性是一个优势,但编写复杂的 GraphQL 查询可能具有挑战性,并且需要仔细规划以提高可读性和可维护性。
- 缓存: 与利用内置 HTTP 缓存机制的 REST API 相比,GraphQL 的数据缓存通常更复杂。
- 安全性: GraphQL 暴露了您的整个数据模式,因此必须采取适当的安全措施以防止未经授权的访问敏感数据。
- 学习曲线: 对于不熟悉 GraphQL 的开发人员,理解模式和查询语法涉及学习曲线。
- 错误处理: 如果库不解析响应体中状态为 200 的错误,则客户端必须使用更复杂的逻辑来处理它们。
它是如何工作的:
- 客户端使用GraphQL语法定义查询,精确指定数据应如何结构化以及需要哪些字段。
- GraphQL服务器使用预定义的模式来确定可用的数据及其与其他数据的关系。这个模式定义了类型、字段以及类型之间的关系。
- 服务器根据模式执行查询。对于查询中的每个字段,服务器都有一个相应的解析函数来获取该字段的数据。
- 服务器返回一个JSON对象,其结构直接反映了查询内容,填充了请求的数据。
GraphQL支持三种核心操作,定义了客户端如何与服务器交互:
- 查询(Queries): 用于从服务器检索数据。这是GraphQL中最常用的操作。
- 变更(Mutations): 在服务器上修改数据。这可能涉及创建新数据、更新现有数据或删除数据。
- 订阅(Subscriptions): 用于在客户端和服务器之间建立实时通信。服务器可以在请求的数据发生变化时更新客户端。
GraphQL请求的一个示例包括一个操作和你请求或操作的数据,例如:
这个查询检索ID为1的用户的数据。它还获取了该用户帖子的嵌套数据,包括它们的ID和标题。
响应是一个JSON对象,包含查询或变更请求的实际数据和可选错误。
要了解更多关于GraphQL的信息,可以查看Eve Porcello和Alex Banks的书籍“Learning GraphQL”。
何时应使用GraphQL、gRPC和REST?
开发者在设计应用程序时可以选择多种客户端-服务器通信协议。在当代项目中,使用GraphQL、gRPC和REST相对常见。每种协议根据您的应用程序需求可以提供不同的优势。
- GraphQL 是一种灵活的数据请求方法,专注于特定请求并仅提供所需数据。它的客户端驱动特性使其与其他API区别开来。客户端做出所有决策,而不是处理它们。GraphQL的优势在于它与语言无关,请求通过单一端点进行,并且是强类型的,因为它有模式。
- REST 是最受欢迎的一个。当一个领域可以被描述为一组资源时,它是一个很好的选择。REST是一种用于数据传输的无状态架构。它的优势包括是一个成熟的标准、简单易用和良好的缓存支持。
- gRPC 是一个轻量级且快速的数据获取系统。这里的主要区别是它如何描述其合同谈判。它依赖于合同;架构不是管理谈判的内容;它是服务器和客户端之间的关系。虽然处理和计算被委托给远程服务器,但大部分能力用于客户端。它的主要优势是它有轻量级客户端,高效率,使用协议缓冲区来发送/接收数据,而且是开源的。
下图显示了最常见的API架构风格的时间线。
API架构风格时间线
因此,何时选择这些协议中的每一个:
- 如果您正在构建一个CRUD风格的Web应用程序或您处理结构化数据良好,使用REST。它是公共API和需要被广泛客户端消费的服务的首选。
- 如果您的API是私有的并且关于行动或性能至关重要,使用gRPC。服务器到服务器通信的低延迟至关重要。它使用HTTP/2和ProtoBuf优化了效率和速度。
- 如果您有一个公共API,需要在定制请求方面灵活,并希望将不同来源的数据添加到公共API中,请使用GraphQL。在客户端-服务器通信中使用它,我们必须在单次往返中获取所有数据。
gRPC与REST与GraphQL比较