GraphQL 比 Rest 更好吗?

2025-06-08

GraphQL 比 Rest 更好吗?

如果您想以声明式的方式工作,GraphQL 是您的不二之选,因为它允许您只选择所需的信息。您需要根据项目的用例来选择。对于某些用户场景,Rest 非常适合,而对于某些用例,您会发现 GraphQL 也表现出色。

在这里,我将逐一讨论何时需要根据用例进行选择:

如果您打算使用 GraphQL,那么在以下情况下,您应该毫不犹豫地使用它:

开发移动应用程序
:在为智能手机、智能手表和物联网设备设计丰富的 UI/UX 应用程序时,最好使用 GraphQL。GraphQL 可以帮助加载用户实际需要的内容,并在网速较慢的情况下保持用户体验。

当您需要处理复杂的模式时,
GraphQL 可以帮助您管理这些复杂的模式。如果您的应用程序基于使用多个嵌套模型和关联的众多模式,那么您应该选择 GraphQL。如果您可能会接触到复杂的查询,那么 REST 在这方面就非常薄弱。作为一种查询语言,GraphQL 可以通过单个 API 请求轻松访问嵌套对象,并返回正确标记的结构化数据(以及 JSON)。

举个例子:

假设我有两个数据库表:

  1. *员工 * - 具有以下列 - 姓名、ID(PK)、电子邮件、手机、城市、部门 ID(FK 引用部门表的部门 ID)
  2. *部门 * - 具有以下列 - 部门名称、部门 ID(PK)

现在

我想获取与人力资源部门相关的员工姓名

如果我使用 Rest,那么我必须编写 Join 查询。但是如果使用 GraphQL,我可以直接使用一个端点查询员工姓名,如下所示

query{
  searchDeptByName(deptName:"HR"){
    employee{
      employeeName****
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

我将收到如下回复:

{
  "data": {
    "searchDeptByName": {
      "employee": [
        {
          "employeeName": "Arya"
        },
        {
          "employeeName": "Tushar"
        },
        {
          "employeeName": "Rekha"
        },
        {
          "employeeName": "Roshan"
        }
      ]
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

这样,GraphQL 就简化了复杂模式的管理(虽然上面的模式不是太复杂,但实际上我们可以有更复杂的模式)

当您想要隐藏后端复杂性时,
GraphQL 具有两个突出的特性,使其成为微服务编排的理想选择。
• 第一个特性允许您抽象 RESTful API,并为微服务创建统一且完全优化的公共 API。此功能的好处是您可以顺利地处理 API 的未来版本。
• 第二个特性处理当您通过将来自多个底层 GraphQL API 的模式拼接在一起来创建单个 GraphQL 模式的情况。
这两个特性都有助于向客户端隐藏代码复杂性。

更佳的开发体验
GraphQL 的最佳使用场景是当您想为开发人员提供更佳体验时。它拥有处理复杂查询的描述性语言、简化状态管理加载的能力以及操作类型的便利性,无需费力调整 JSON 数据。

当您的应用程序从多个资源接收数据时,
GraphQL 会公开一个端点,允许您访问多个资源。此外,资源的公开方式不会根据您应用程序内部的视图而有所不同。因此,如果您的 UI 发生变化(例如,需要更多或更少的数据),它不会对服务器产生影响,也不需要进行任何更改。

图片描述

现在你应该放弃在以下情况下使用 GraphQL 的想法。

如果您已经拥有 REST,
GraphQL 是 REST 的有效替代方案。如果您熟悉 REST,何必再苦苦寻找替代品呢?GraphQL 的主要功能是发送包含您所需精确信息的查询。但是,使用 REST 可以轻松实现这一点——从传递字段名称到在 URL 中使用它。此外,还有许多 JSON 库可以帮助您实现和支持此规范。

何时使用 Web 缓存?
在数据库级别或客户端级别实现 Web 缓存(使用内存缓存实现)可能很容易。在 HTTP 级别实现缓存,并使用反向代理服务器存储请求内容,可以减少到达服务器的流量。由于 REST 提供了众多端点,因此可以轻松地将 Web 缓存配置到 URL。

当性能成为您的首要任务时,
GraphQL 能够执行查询以获取精确的结果。但是,如果客户端发送查询涉及大量字段和资源,您可能会面临性能问题。对于复杂的查询,GraphQL 必须经过精心设计,不能仅仅将其放在 REST API 或数据库上。您必须定义每个端点并调整查询以检索特定数据。所有这些设计和定义都会影响 API 的性能。

举个例子:

提供对该作者的所有书籍发表评论的用户的信息

author(id: '1234') {
  id
  name
  books {
    id
    title
    reviews {
      text
      date
      user {
        id
        name
      }
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

您可以让用户运行任何他们想要的查询。GraphQL API 必须经过精心设计;它不仅仅是将其置于 REST API 或数据库之上。

对于复杂的查询,REST API 可能更容易设计,因为您可以根据特定需求建立多个端点,并且对于每个端点,您可以微调特定的查询以有效的方式检索数据。

这可能有点争议,因为多次网络调用也会耗费大量时间。但如果你不小心,几个大型查询就可能导致服务器瘫痪。从这个意义上讲,GraphQL 最大的优势也可能是它最大的弱点。

REST 更适合错误处理和工具化
。与 GraphQL 相比,REST 中的错误处理更容易。RESTful API 在资源方面遵循 HTTP 规范,
并针对不同的 API 请求状态返回不同的 HTTP 状态。而 GraphQL 会为每个 API 请求(包括错误)返回200 Ok状态。这使得错误管理变得困难,并且难以与监控工具集成。

现在回到安全性问题。GraphQL
的安全性是否低于 Rest?

绝对不是!
GraphQL 是一种非常强大的查询语言,可以完美地完成很多事情。如果正确实现,GraphQL 可以提供极其优雅的数据检索方法、更高的后端稳定性以及更高的查询效率。

但这里的关键就是这个简单的短语——正确实施。

有很多方法可以保护 GraphQL 查询:

1. 身份验证
身份验证是指确定特定用户是否已登录,并随后记住其身份。身份验证可以为会话提供上下文,并个性化用户看到的数据类型。

2. 授权
授权就是确定特定用户有权执行或查看哪些操作。在 GraphQL 中,我们使用它来根据身份、角色或权限管理对特定查询和变更的访问。

为了实现身份验证和授权,我们可以利用 Spring Security 的 Oauth2/JWT。此外,还有很多其他工具可以使用。如果将应用程序部署到 Google Cloud,我们可以使用 Apigee 作为 API 网关来执行身份验证和授权。

3. 限制查询深度
GraphQL 允许客户端以多种不同的方式请求数据。由于可用的入口点不同,

ilable to request data, it’s possible to write exceptionally large nested queries like the following.

query{
  searchDeptByName(deptName:"HR"){
    employee{
      employeeName
      department{
        deptName
        employee{
          employeeName
          department{
            deptName
            employee{
              employeeName
              # and so on
            }
          }
        }
      }
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

此类查询非常危险,因为它们的计算成本很高。它们可能会导致我们的 API 崩溃,并占用所有可用资源。

我们可以通过在 Spring application.properties 中添加以下属性来指定查询的最大深度,以缓解此问题

graphql.servlet.maxQueryDepth= 3 # 这里 3 是最大查询深度

现在如果我们执行上述查询,我​​们将会得到错误:

{
  "errors": [
    {
      "message": "maximum query depth exceeded 7 > 3",
      "extensions": {
        "classification": "ExecutionAborted"
      }
    }
  ]
}
Enter fullscreen mode Exit fullscreen mode

3. 在适当的地方对列表字段进行分页

查询深度并非唯一需要担心的事情。我们还应该意识到查询量会如何影响 API 的性能。

在以下示例中,如果有 10 个部门,每个部门有 100 名员工,则此查询将尝试返回 100,000 个节点。

query{
  searchAllDepartments( {
      deptName
      employee{
        employeeName
        city
        country
        deptId
        dob
        email
        employeeId
      }
    }
}
Enter fullscreen mode Exit fullscreen mode

为了解决这个问题,我们可以使用分页。使用 Spring Boot 很容易。我们只需要从Repository扩展PagingAndSortingRepository
接口,并 在 Service 类中实现相应的方法即可。

4. 改进验证和过滤机制。
验证和过滤是标准的 Web 应用程序安全实践。当你接受用户数据时,应该始终验证并过滤用户提供的数据,因为这些数据可能是恶意的。

5. 使用超时机制
当我们从下游服务或数据源请求数据时,有多种原因可能导致响应时间过长。例如,服务可能宕机、查询开销过大,或者发生了其他问题。无论原因是什么,我们都不希望 GraphQL API 长时间挂起等待响应。

为了防止这种情况,我们需要使用超时来防止缓慢或无响应的服务影响后续
查询的性能。

我们可以利用以下属性从 Spring application.properties 设置超时。

spring.jpa.properties.javax.persistence.query.timeout=60000 #该值为超时时间,单位为毫秒

6. 掩码错误

当服务器或下游服务发生错误时,最好屏蔽/隐藏客户端出错的具体细节。我们应该显示自定义异常消息。

将服务器中的错误详细信息告知客户端会暴露当前服务器的漏洞并为更集中的攻击打开大门。

GraphQL 应用程序是否像 Rest 一样稳定?

使用 GraphQL 的应用程序快速且稳定,因为它们控制获取的数据,而不是服务器。

概括:

图片描述

结论:

GraphQL 是 REST 的绝佳替代方案,但并非适用于所有情况。因此,在使用 GraphQL 之前,请评估您的应用程序及其想要集成的功能。在正确的场景中使用 GraphQL,效果会非常出色!

鏂囩珷鏉ユ簮锛�https://dev.to/arpanforgeek/is-graphql-better-option-than-rest--5a62
PREV
Java Solid 原则指南
NEXT
全栈 Instagram:简介