GraphQL与REST:两种API架构

简介: 在过去十年中,REST已经成为Web API的设计标准,提供了一些很棒的想法,例如无状态服务器和对资源的结构化访问,可以去这里详细了解REST API。但是,REST API已经显示出太不灵活,无法满足访问客户端快速变化的需求。

image.png

GraphQL 既是一种用于 API 的查询语言也是一个满足你数据查询的运行时。 GraphQL 对你的 API 中的数据提供了一套易于理解的完整描述,使得客户端能够准确地获得它需要的数据,而且没有任何冗余,也让 API 更容易地随着时间推移而演进,还能用于构建强大的开发者工具。

在过去十年中,REST已经成为Web API的设计标准,提供了一些很棒的想法,例如无状态服务器和对资源的结构化访问,可以去这里详细了解REST API。但是,REST API已经显示出太不灵活,无法满足访问客户端快速变化的需求。

GraphQL的开发是为了满足更高灵活性和效率的需求!它解决了开发人员在与REST API交互时遇到的许多缺点和低效问题。

REST和GraphQL区别

为了说明从API获取数据时REST和GraphQL之间的主要区别,让我们考虑一个简单的示例场景:在博客应用程序中,应用程序需要显示特定用户的帖子标题。同时还显示该用户的最后3个关注者的姓名。

如何通过REST和GraphQL解决这种情况?

使用REST与GraphQL进行数据获取

使用REST API,需要设计三个接口来获取数据:

  • /users/<id> :获取初始用户数据
  • /users/<id>/posts : 返回用户的所有帖子
  • /users/<id>/followers :返回每个用户的关注者列表。

image.png

GraphQL中只需向GraphQL服务器发送一个包含具体数据要求的查询。然后,服务器使用JSON对象进行响应,满足需求。

image.png

使用GraphQL,客户端可以准确指定查询中所需的数据属性。

REST

REST 是最通用,也是最常用的接口设计方案,它是无状态的,以资源为核心,针对如何操作资源定义了一系列 URL 约定,而操作类型通过 GETPOSTPUTDELETE 等 HTTP Methods 表示。

  • 下载多余的数据
    客户端下载的信息量超过了应用程序中实际需要的信息量。例如一个页面,只需要显示一个用户名列表。在REST API中,此应用程序通常会命中/users接收带有用户数据的JSON数组,为了通用性,该接口可能返回更多的用户信息,如生日或者地址。
  • 信息缺失和N+1问题
    信息缺失通常意味着特定接口不能提供足够的所需信息。客户端需要提出额外的接口来获取所需要的信息。

GraphQL

GraphQL 不是 REST 的替代品,而是另一种交互形式:前端决定后端的返回结果

GraphQL API 的主要应用场景是 API 网关,在客户端和服务之间提供了一个抽象层。

image.png

GraphQL 带来的最大好处是精简请求响应内容,不会出现冗余字段,前端可以决定后端返回什么数据。但要注意的是,前端的决定权取决于后端支持什么数据,因此 GraphQL 更像是精简了返回值的 REST,而后端接口也可以一次性定义完所有功能,而不需要逐个开发。现在来说说GraphQL带来的好处:

  • 提高开发速度
    首先,GraphQL 有助于减少请求数。通过单个调用来获取所需的数据比使用多个请求要容易得多。从开发的角度来看,这加快了开发速度。
    后端和客户端团队需要通过密切合作来定义 API、测试,并做出更改。前端、移动、物联网等客户端团队不断迭代功能,并尝试使用新的 UX 和设计。数据需求经常会发生变化,后端团队必须跟上节奏。如果客户端和后端代码由同一团队负责,那么问题就没那么严重了。
    使用GraphQL,客户端工程师可以完全控制前端,不需要依赖任何人,因为可以使用GraphQL查询告诉后端他们需要什么以及响应结构应该是怎样的。而不需要花时间让后端 API 团队添加或修改某些内容。
    GraphQL 具有自文档的特点,可以节省一些用于查找文档以便了解如何使用 API 的时间。
    当拥有大量 GraphQL API后,然后有人想出了一个新的产品创意,使用已有的 GraphQL API 可以快速实现原型,比调用各种 REST API 或为新应用程序构建新的 REST API 要快得多。
  • 提升性能工程师并不是唯一从GraphQL中受益的人。用户也会从中受益,因为应用程序的性能获得了提升(可以感知到的):
  • 减少了有效载荷(客户端只需要必要的东西)
  • 多个请求合并为一个请求可减少网络开销;
  • 更快的 UI 更新
  • 改进的安全性、强类型和验证
    GraphQL 的 schema 与语言无关。对前面的示例进行扩展,我们可以在 schema 中定义 Address 类型:
type Address {
    city: String!
    country: String!
    zip: Int
}
  • String 和 Int 是标量类型,! 表示字段不可为空。
    schema 验证是 GraphQL 规范的一部分,因此像这样的查询将返回错误,因为 name 和 phone 不是 Address 对象的字段:
{
    user (id: 123) {
        address {
            name
            phone
        }
    }
}

GraphQL 的实现

在选择实现 GraphQL API 的平台时,Node 是一个候选项,因为最初 GraphQL 用于 Web 应用程序和前端,而 Node 是开发 Web 应用程序的首选,因为它是基于 JavaScript 的。使用 Node 可以非常容易地实现 GraphQL(假设提供了 schema)。《NodeJs中使用Apollo Server构建GraphQL API服务》完整的实现了GraphQL API。事实上,使用 Express 或 Koa 来实现只需要几行代码:

const Koa = require('koa');
const Router = require('koa-router'); // koa-router@7.x
const graphqlHTTP = require('koa-graphql');
const app = new Koa();
const router = new Router();
router.all('/graphql', graphqlHTTP({
  schema: schema,
  graphiql: true
}));
app.use(router.routes()).use(router.allowedMethods());

schema 是使用 npm 的 graphql 中的类型来定义的。Query 和 Mutation 是特殊的 schema 类型。

GraphQL API 的大部分实现都在于 schema 和解析器。解析器可以包含任意代码,但最常见的是以下五个主要类别:

  • 调用 Thrift、gRPC 或其他 RPC 服务;
  • 调用 HTTP REST API(当优先事项不是重写现有 REST API 时);
  • 直接调用数据存储;
  • 调用其他 GraphQL schema 查询或服务;
  • 调用外部 API。

GraphQL 不一定需要客户端。一个简单的 GraphQL 请求就是一个常规的 POST HTTP 请求,其中包含了查询内容。我们可以使用任意的 HTTP 代理库(如 CURL、axios、fetch、superagent 等)来生成请求。例如,在终端中使用 curl 发送请求:

curl \
  -X POST \
  -H "Content-Type: application/json" \
  --data '{ "query": "{ posts { title } }" }' \
  https://1jzxrj179.lp.gql.zone/graphql

以下代码可以在任意一个现代浏览器(为了避免 CORS,请访问 launchpad.graphql.com)中运行。

fetch('https://1jzxrj179.lp.gql.zone/graphql', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ query: '{ posts { title } }' }),
})
  .then(res => res.json())
  .then(res => console.log(res.data));

虽然构建 GraphQL 请求很容易,但是还需要实现很多其他东西,比如缓存,因为缓存可以极大地改善用户体验。构建客户端缓存不是那么容易,所幸的是,Apollo 和 Relay Modern 等提供了开箱即用的客户端缓存。

什么时候不该使用 GraphQL?

当然,完美的解决方案是不存在的(尽管 GraphQL 接近完美),还有一些问题需要注意,例如:

  1. 它有单点故障吗?
  2. 它可以扩展吗?
  3. 谁在使用 GraphQL?

最后,以下列出了有关 GraphQL 可能不是一个好选择的主要原因:

  • 当客户端的需求很简单时:如果你的 API 很简单,例如 /users/resumes/123,那么 GraphQL 就显得有点重了;
  • 为了加快加载速度使用了异步资源加载;
  • 在开发新产品时使用新的 API,而不是基于已有的 API;
  • 不打算向公众公开 API;
  • 不需要更改 UI 和其他客户端;
  • 产品开发不活跃;
  • 使用了其他一些 JSON schema 或序列化格式。
相关文章
|
8天前
|
JavaScript API 开发者
GraphQL API开发入门:比RESTful更高效的数据查询方式
**GraphQL API开发入门摘要** GraphQL是一种更高效的数据查询方式,解决RESTful API的过度或不足获取数据问题。它允许客户端按需获取数据,减少网络传输,支持一次请求获取多资源。强类型和自描述特性方便了开发。文章通过一个简单的Node.js示例,展示如何使用`apollo-server-express`搭建GraphQL服务器,包括定义Schema、实现Resolver和创建服务器。通过测试,显示了GraphQL如何提供精确数据和优化查询效率。对于复杂数据需求,GraphQL是现代API设计的有效选择。
17 0
|
3天前
|
开发框架 Java API
Java中的REST API开发详解
Java中的REST API开发详解
|
3天前
|
负载均衡 安全 前端开发
深入理解微服务架构中的API网关
【7月更文挑战第4天】本文旨在探讨微服务架构中的关键组件——API网关,分析其作用、设计原则及实现方式。通过对比不同场景下的应用实例,揭示API网关在微服务生态系统中的重要性和实现细节。
15 2
|
3天前
|
负载均衡 监控 安全
微服务架构中的API网关模式解析
【7月更文挑战第4天】在微服务架构中,API网关不仅是一个技术组件,它是连接客户端与微服务之间的桥梁,负责请求的路由、负载均衡、认证、限流等关键功能。本文将深入探讨API网关的设计原则、实现方式及其在微服务架构中的作用和挑战,帮助读者理解如何构建高效、可靠的API网关。
|
6天前
|
缓存 监控 负载均衡
微服务架构下的API网关设计与实现
在分布式系统和微服务架构中,API网关扮演着至关重要的角色。它不仅是服务的单一入口点,还负责请求的路由、负载均衡、认证授权、限流熔断等关键功能。本文将深入探讨API网关的设计理念、核心组件以及实现策略,旨在为开发者提供一套完整的API网关解决方案。通过分析现代微服务架构的需求,结合最新的技术趋势,我们将展示如何构建一个高效、可靠且易于维护的API网关。
19 0
|
6天前
|
开发框架 安全 .NET
使用VB.NET构建Web服务和REST API的指南
【7月更文挑战第2天】使用VB.NET构建Web服务和REST API的指南:从Web服务基础到ASP.NET Core实践,涵盖控制器、路由、模型绑定、安全措施(如JWT、HTTPS)及测试、部署(Azure、Docker)与监控工具。了解如何利用VB.NET在现代云环境中创建高效、安全的API。开始你的VB.NET Web服务开发之旅!**
9 1
|
6天前
|
监控 安全 API
探索微服务架构中的API网关模式
【7月更文挑战第2天】在微服务的大潮中,API网关作为系统的大门守卫,不仅负责请求的分发和聚合,还承担着安全、监控等关键职责。本文将深入探讨API网关的设计原则、核心功能以及在微服务架构中的实际应用案例,为开发者提供实现高效、可扩展API网关的实用指南。
11 1
|
7天前
|
设计模式 负载均衡 安全
探索微服务架构中的API网关模式
【6月更文挑战第30天】在微服务架构的海洋中,API网关犹如一座灯塔,指引着服务的航向。本文将深入剖析API网关的设计哲学、核心功能以及其在微服务生态中扮演的角色,同时探讨如何实现一个高效、可靠的API网关,并分析其对系统性能与安全性的影响。
|
4天前
|
开发框架 Java API
Java中的REST API开发详解
Java中的REST API开发详解
|
5天前
|
缓存 Java API
Java中设计和优化REST API的技巧
Java中设计和优化REST API的技巧