GraphQL的15个典型情况及解析,包括有和没有的情况

引言

这是DMM集团2020年Advent Calendar第六天的文章。

我认为如今有越来越多的人看到了GraphQL的机会并考虑过尝试使用它。

为了避免在实施后惊呼“不应该这样的!”或者“应该多考虑一些!”这样的情况发生,关于GraphQL只着眼于好处而很少讨论与GraphQL相关的失败和错误的问题,这种情况就类似于銀河弹那样特别容易引起人们的注意。

在做GraphQL时,
– 看过
– 听过
– 做过
– 有过误解
这样的常见情况(包括不存在的情况)我简单介绍一下。

(※因为有一些夸张的地方,请注意)

GraphQL 的常见情况

我将以以下三个方面介绍GraphQL的常见用法。

1. GraphQL的典型应用场景
2. GraphQL带来的好处
3. 使用GraphQL时可能遇到的挑战

    1. 数据库架构

 

    1. 版本管理和更新

 

    性能优化

模式编辑

1. 不采用GraphQL的架构优先开发,而是采用数据库架构优先开发。

使用GraphQL时,通常会采用模式优先的设计方法。

在以Schema First进行开发时,所有团队成员可以使用共同的数据类型作为交流的语言。然而,很少但还是会发生以下这种情况。

我想要获取这个SQL查询的结果的查询语句…神秘的人(ry

2. 数据库和一个对应的字段名称不明确的字段出现。(○○_id)

GraphQL的对象类型字段名并不需要与数据库表字段名相匹配,也不需要公开不必要的字段。

经常见到的形状 de

{
  user {
    name
    home {
      id
      country
      prefecture
      city
    }
  }
}

困惑的形状

{
  human {
    name
    home_id
  }
}

3. 不使用GraphQL的对象类型,而是扁平化地产生大量字段。

假设在数据库的User表中有关于某个人居住地的信息。

假设这些信息都与国家、县、城市等居住相关,您也可以将其汇总到对象“Home”中。
特别是在可以整合为一体或有可能再次利用的情况下,将其合并在一起会更好。

请帮我翻译以下内容:

经常见到的形状

{
  user {
    name
    home {
      country
      prefecture
      city
    }
  }
}

困扰的形式

{
  user {
    name
    country
    prefecture
    city
  }
}

如果使用GraphQL的话,如果不需要字段,就不需要调用它们,这样就会产生无用的字段。

GraphQL被认为可以避免过度获取数据(过度获取)。
然而,是否需要将所有字段都添加进来呢?我相信并不需要。

我喜欢吃中国菜。

我爱吃中国饭。

常见的形状

{
  user {
    name
    home {
      id 
      country
      prefecture
      city
    }   
  }
}

困扰的形状 de

{
  user {
    home {
      id 
      country
      prefecture
      city
    }
    deleted_at
  }
}

5. 虽然不像REST API那样URL数量繁多,但是存在大量令人困扰的查询。

与REST类似的API相比,GraphQL不会像URL一样随着用例的增加而不断增多。
然而,复杂的查询可能会不断增加。

举一个简单的例子,可能有时候我们希望从用户信息中排除管理员的信息,
或者只想要当天创建的用户信息。
另外,在特定条件下可能希望将某些参数设为必需。

当遇到这些许多用例时,可以选择将其添加为用户查询的参数,也可以选择对查询进行分割。

如果负责管理架构的人或部门没有进行适当管理,就可能出现非常复杂的参数查询,或者大量生成相似但不同的查询的情况。

I am happy.

- user
- userExculdAdmin
- userCretedToday

制作独特的定制颜色并遭受痛苦(这个模具能放入什么?)

在GraphQL中,可以自定义标量类型,并且这些类型也被称为自定义标量。
然而,很多客户端无法自动解释自定义标量。

换句话说,除去明显明了的类型或极其易懂的类型之外,客户端很难在自定义类型的优点上实施有效的验证。

比如,URL和JSON可以具有一些共同的验证方法概念。
那么密码呢?密码的基本验证方法呢?
在最坏的情况下,我们不能期望密码的验证仅限于它是一个字符串类型。

有一定程度上自明的形式

- URL
- JSON

令人困惑的形状 shí

- Password
- OfficialId

其实,我们并不需要GraphQL。

在以下情况下,如果很难向人们展示GraphQL的好处时,老实说,采用CRUD形式的类似REST的API可能已经足够了。

– 你去图书馆学习了吗?
– 你有没有去图书馆学习?
– 你是否到图书馆自习了?
– 你是去图书馆学习了吗?

    • オブジェクト間がGraph構造のようになんらかの繋がりをほぼ持っていない場合。

 

    • 操作すべきオブジェクトが2~3しかなく、1つのオブジェクトのフィールドも5つとかである場合。

 

    • セキュア情報をやり取りしたいけど、キャッシュをバキバキに効かせたい場合

 

    • (GraphQLはREST likeなAPIと比較するとキャッシュしづらいです。GETでやる方法もありますが…)

 

    • リクエストの送信元がスペックが十分にあり(サーバー間通信目的など)、

 

    なおかつAPIを呼ぶ頻度も十分に少ないような場合。

版本控制和更新模块

8. 删除字段无法立即完成。现有客户端将会死机。

Q. GraphQL是不是可以立即删除字段?

A. 无法删除,可能会导致现有的客户端停止工作。建议您将其标记为@deprecated,在确认未被调用一段时间后再删除。

A. 虽然可以将GraphQL标注为@deprecated,但无法完全强制客户端不再调用。

9. 添加必要的参数不能立即完成,因为会导致现有的客户端程序崩溃。

Q. 我想要为○○查询添加必需的参数,但如果使用GraphQL的话,会比较好,对吧?
A. 基本上不能立即添加必需的参数。
现有的客户端可能会引发错误,而无法全部适应。

10. GraphQL会根据指定的字段进行调用,因此一旦不再需要,就能立即意识到。

由于GraphQL指定了要获取的字段,因此当某个字段不再被调用时,不必要的字段就比较容易理解。

然而,在优先级和紧急性上,许多重构任务可能会被延后处理。因此,不会立即删除相关字段,直到所有客户都不需要该字段为止。

换句话说,通过类似于记录字段未被调用的日志结果,我们可以判断该字段是不必要的。但是,由于存在持续调用该字段的客户端,很难察觉客户端需求不再需要该字段的时机。

11. 不需要版本控制吗? (Bù ma?)

我想可能有一些人认为GraphQL不需要版本控制。

如果GraphQL具有新的类型和这些新类型的字段,那么添加新功能等会更加容易,只要基本设计相对稳定,就不一定需要进行版本管理。

然而,在上述的1,2,3案例以及有关GraphQL和模式设计的知识尚未集结之前,大规模的模式更改可能会发生,因此我认为在某些情况下最好进行版本管理。

表演部分

12. GraphQL = 引发 N+1 问题

在GraphQL中,通常会为类型和字段指定解析值的函数。然而,由于每个函数都会向数据库或API发送请求,这可能导致包含N+1问题的许多性能问题。

不过,无论怎么挣扎,也不一定会遇到N+1问题。
可以利用类似Facebook的DataLoader工具,
或者实现任意的缓存和批处理机制,这样可以在一定程度上缓解问题。

参考:graphql/dataloader 可以在 GitHub 上找到,链接为 https://github.com/graphql/dataloader。

13. 起初我想把请求的大小缩小,但追踪结果却使扩展体积膨胀了。

GraphQL 不是基于 URL 的请求方式,而是根据指定的字段进行处理。
因此,无法通过监控 URL 的方式来实现性能监控。

在这种情况下,可以考虑通过GraphQL服务器的解析器在唯一请求ID上记录每个操作的时间,并将其输出到日志中,或者在GraphQL响应的extensions中包含处理时间等信息并返回。

让我们来看一个后者情况的例子。这是一个关于apollo跟踪的示例。

{
  "data": <>,
  "errors": <>,
  "extensions": {
    "tracing": {
      "version": 1,
      "startTime": <>,
      "endTime": <>,
      "duration": <>,
      "parsing": {
        "startOffset": <>,
        "duration": <>,
      },
      "validation": {
        "startOffset": <>,
        "duration": <>,
      },
      "execution": {
        "resolvers": [
          {
            "path": [<>, ...],
            "parentType": <>,
            "fieldName": <>,
            "returnType": <>,
            "startOffset": <>,
            "duration": <>,
          },
          ...
        ]
      }
    }
  }
}

如您所见,响应可能会变得过于庞大。
然而,通过对HTTP响应体进行压缩,可以在一定程度上缓解这种响应的庞大化。

参考:apollographql/apollo-tracing(https://github.com/apollographql/apollo-tracing)

14. 更改为GraphQL后变慢了!发送数据库查询更快啊!

经常听到这样的情况,当管理界面的系统除了数据库等之外,都在一个服务器上完成时,将其划分为管理界面和GraphQL的API。

在这种情况下,

谜人:与原来完整的系统相比,变得更慢了!
我:?

如果在没有承受任何负荷的情况下,只关注速度方面,一般来说,相比于向数据库发送一个查询处理,GraphQL的API请求往往会更慢。在这种情况下,我们需要考虑GraphQL的优点和折衷之处。

15. 停止恶意查询很困难,会对性能产生影响。

为了阻止对性能产生影响的恶意查询,通常会设置以下限制:
– 查询深度限制
– 查询复杂度限制(例如,所有字段分数的总和等)
– 基于请求本身的超时限制

然而,无论是字段深度限制还是复杂度限制,在区分每个字段对性能的影响(是大还是小)方面并没有进行区分。此外,如果将这些限制设置得过小, introspection 查询也会出错。

尾声

到目前为止,我稍微夸张地介绍了GraphQL的一些普遍问题。

由于这些很大程度上取决于上下文,因此也有一些无法避免的情况。
另外,关于实际情况如何?如何思考?在正文中无法详细说明,请谅解只能大致介绍。
(希望在某个学习会或LT会等地,能有机会进行意见交流)

我知道很多人可能会觉得不会去做(考虑)那样的事情,但我希望这对于考虑采用GraphQL的人来说能够有一些参考价值。

DMM集团2020年圣诞日历第7天是由@mesh1nek0x0负责。

广告
将在 10 秒后关闭
bannerAds