良好的API设计对任何一个系统都是关键部分,但选择正确的API技术也很重要。在本教程中,我们将简要讨论不同的API技术,如REST、GraphQL和gRPC。
什么是API?
在我们进入API技术之前,让我们先了解什么是API。
API代表应用程序编程接口。它是一组用于构建和集成应用软件的定义和协议。它有时被称为信息提供者和信息使用者之间的契约,建立来自生产者的消费者所需内容。
换句话说,如果你希望与计算机或系统交互以获取信息或执行功能,API将帮助你向该系统传达你想要表达的信息,以便它能够理解并完成请求。
REST
REST API(也称为RESTful API)是一种应用程序编程接口,它符合 REST 架构风格的约束,并允许与 RESTful Web 服务交互。REST含义为表征状态转移(Representational State Transfe),由 Roy Fielding 于2000年首次引入。
在REST API中,基本单元是资源。
概念
让我们讨论 RESTful API 的一些概念。
约束
API必须符合以下架构约束才被视为RESTful:
- 统一接口:应该有一种与给定服务器交互的统一方式。
- 客户端-服务器:通过HTTP管理的客户端-服务器架构。
- 无状态:请求之间不应在服务器上存储客户端上下文。
- 可缓存:每个响应都应该包括响应是否可缓存,以及在客户端缓存响应的持续时间。
- 分层系统:应用程序架构需要由多层组成。
- 按需编码:返回可执行代码以支持应用程序的部分功能。(可选)
HTTP动词
HTTP定义了一组请求方法,以指示要对给定资源执行的所需操作。虽然它们也可以是名词,但这些请求方法有时被称为HTTP动词。它们中的每一个都实现了不同的语义,但共享一些共同的特性。
- GET:请求指定资源的表示形式。
- HEAD:响应与GET请求相同,但没有响应主体。
- POST:将实体提交到指定的资源,通常会导致服务器的状态更改或产生其他影响。
- PUT:用请求负载替换目标资源的所有当前表示。
- DELETE:删除指定的资源。
- PATCH:对资源应用部分修改。
HTTP响应码
HTTP响应状态码指明特定HTTP请求是否已成功完成。
标准中定义了五类:
- 1xx-信息性响应。
- 2xx-成功响应。
- 3xx-重定向响应。
- 4xx-客户端错误响应。
- 5xx-服务器错误响应。
例如,HTTP 200表示请求成功。
优点
让我们看一下REST API的优点:
- 简单易懂。
- 灵活性和简便性。
- 良好的缓存支持。
- 客户端和服务器是解耦的。
缺点
让我们看一下REST API的缺点:
- 过度获取数据。
- 有时需要多次往返服务器。
使用场景
REST API被广泛使用,是设计API的默认标准。总的来说,REST API非常灵活,可以适应几乎所有的场景。
例子
下面是在 users 资源上操作的 REST API 的示例用法。
| URI | HTTP 动词 | 说明 |
|---|---|---|
| /users | GET | 获取所有用户 |
| /users/{id} | GET | 根据id获取用户 |
| /users | POST | 添加一个新用户 |
| /users/{id} | PATCH | 根据id更新用户 |
| /users/{id} | DELETE | 根据id删除用户 |
REST API中还有很多东西需要学习,我强烈建议看一下 Hypermedia as the Engine of Application State (HATEOAS)。
GraphQL
GraphQL 是 API 的查询语言和服务器端运行时,它优先为客户端提供它们所请求的数据。它是由 Facebook 开发的,后来在2015年开源。
GraphQL旨在使API快速、灵活且对开发人员友好。此外,GraphQL 使 API 维护人员可以灵活地添加或弃用字段,而不会影响现有查询。开发人员可以使用他们喜欢的任何方法构建API,GraphQL 规范将确保它们以客户端可预测的方式运行。
在GraphQL中,基本单元是查询。
概念
让我们简要讨论 GraphQL 中的一些关键概念:
模式
GraphQL 模式描述了客户端连接到 GraphQL 服务器后可以使用的功能。
查询
查询是客户端发出的请求。它可以由查询的字段和参数组成。查询的操作类型也可以是 Mutation,它提供了一种修改服务器端数据的方法。
解析器
解析器是为 GraphQL 查询生成响应的函数集合。简单来说,解析器充当 GraphQL 查询处理程序。
优点
让我们看一下 GraphQL的优点:
- 消除了数据的过度获取。
- 强定义模式。
- 代码生成支持。
- 有效负载优化。
缺点
让我们看一下 GraphQL 的缺点:
- 将复杂性转移到服务器端。
- 缓存变得困难。
- 版本控制不明确。
- N+1 问题。
使用场景
GraphQL在以下场景中非常重要:
- 减少应用带宽使用,因为我们可以在单个查询中查询多个资源。
- 复杂系统的快速原型设计。
- 当我们使用类似图的数据模型时。
例子
这是一个定义 User 类型和 Query 类型的 GraphQL 模式。
type Query {
getUser: User
}
type User {
id: ID
name: String
city: String
state: String
}
使用上述模式,客户端可以轻松地请求所需字段,而无需获取整个资源或猜测 API 可能返回的内容。
{
getUser {
id
name
city
}
}
这将向客户端提供以下响应。
{
"getUser": {
"id": 123,
"name": "Karan",
"city": "San Francisco"
}
}
了解更多关于GraphQL的信息,请访问 graphql.org。
gRPC
gRPC是一个现代的开源高性能远程过程调用(Remote Procedure Call,RPC)框架,可以在任何环境中运行。它可以有效地连接数据中心内和跨数据中心的服务,并对可插拔的负载平衡、跟踪、健康检查、身份验证等功能提供支持。
概念
让我们看一下 gRPC 的一些关键概念。
协议缓冲区
协议缓冲区(Protocol buffers)提供了一种语言和平台无关的可扩展机制,用于以向前和向后兼容的方式序列化结构化数据。它类似于JSON,只是它更小更快,并且生成本地语言绑定。
服务定义
与许多RPC系统一样,gRPC 基于定义服务并指定可以远程调用的方法及其参数和返回类型的思想。gRPC 使用协议缓冲区作为接口定义语言(Interface Definition Language,IDL),用于描述服务接口和有效负载消息的结构。
优点
让我们看一下 gRPC 的一些优点:
- 轻量、高效。
- 高性能。
- 内置代码生成支持。
- 双向流。
缺点
让我们看一下 gRPC 的一些缺点:
- 与REST和GraphQL相比出现时间短。
- 有限的浏览器支持。
- 学习曲线陡峭。
- 可读性差。
使用场景
以下是适合使用 gRPC 的一些场景:
- 通过双向流进行实时通信。
- 微服务中的高效服务间通信。
- 低延迟和高吞吐量通信。
- 多语言环境。
例子
以下是在 *.proto 文件中定义 gRPC 服务的基本示例。使用这个定义,我们可以很容易地用我们选择的编程语言编码生成 HelloService 服务。
service HelloService {
rpc SayHello (HelloRequest) returns (HelloResponse);
}
message HelloRequest {
string greeting = 1;
}
message HelloResponse {
string reply = 1;
}
REST vs GraphQL vs gRPC
我们已经知道了这些 API 设计技术的工作原理,我们可以根据以下参数对它们进行比较:
- 是否会导致紧耦合?
- API有多繁琐(不同的API调用以获取所需信息)?
- 性能怎么样?
- 集成有多复杂?
- 缓存工作得如何?
- 内置工具和代码生成?
- API可发现性是什么样的?
- API版本管理容易吗?
| 类型 | 耦合 | 繁琐 | 性能 | 复杂性 | 缓存 | 代码生成 | 可发现性 | 版本管理 |
|---|---|---|---|---|---|---|---|---|
| REST | 低 | 高 | 好 | 中 | 很好 | 差 | 好 | 简单 |
| GraphQL | 中 | 低 | 好 | 高 | 一般 | 好 | 好 | 一般 |
| gRPC | 高 | 中 | 很好 | 低 | 一般 | 很好 | 差 | 困难 |
哪种API技术更好?
好吧,答案是没有。没有解决一切的灵丹妙药,因为每种技术都有各自的优缺点。用户只关心以一致的方式使用我们的API,因此在设计 API 时,请确保关注你的领域和需求。