初识 GraphQL 和 Apollo Federation

初识 GraphQL 和 Apollo Federation,第1张

初识 GraphQL 和 Apollo Federation

目录

背景为什么要用 GraphQL?为什么要用 Apollo Federation一个真实的案例小结:什么样的团队适合使用 GraphQL

背景

GraphQL 自诞生以来就被寄予厚望,被认为是一种有望替代 REST 的新一代服务端调用方式。

而 Apollo Federation 这个工具是对 GraphQL 的一种增强,让 GraphQL 能够更好地应用在微服务架构下。

下面就来简单分析一下,为什么要使用 GraphQL / Apollo Federation?

为什么要用 GraphQL?

那么,GraphQL 比 REST 好在哪里呢?

在 GraphQL 中,是客户端指定自己要获取哪些字段、哪些对象。这样一来,既不会多拿(Overfetch),也不会少拿(Underfetch),一个请求刚好拿到自己全部所需的数据,没有时间或者带宽上的浪费,岂不痛快!在 REST 中,接口返回什么数据是确定的,这样一来就很可能会出现“多拿”或者“少拿”的情况;

举个例子:假设你想查询一部电影的相关信息,至少有两种情况:

场景 1:在推荐列表/搜索结果页,这时对于每一部电影,只需要显示很少的信息,例如标题、标签、评分,等等;场景 2:在详情页,这时候需要显示关于这部电影的很多信息,包括完整描述、所获奖项、剧照、影评,等等;

如果只用一个 REST 接口满足两种场景,永远返回全部数据(现实中应该没人这么干),那么在场景 1 中,客户端就会收到大量无用的数据;

如果用两个 REST 接口分别供这两种场景调用(现实中应该会是这样),那么对服务提供方和调用方来说维护成本都很高。假如某个场景发生变化,或者新增了场景,那么服务端还需要修改或者新增接口;

还有一种 REST 的思路是,在请求参数中指定需要返回哪些数据,或者指定当前是哪种场景。但这样还是会提高维护成本,而且既然都想这么做了,为啥不直接用 GraphQL 呢??毕竟 GraphQL 其实就是在 REST 上增加了一层,来自动化地实现“指定返回哪些数据”的功能呀!

相比之下,使用 GraphQL 的好处就显而易见了:只需要一个接口,客户端在查询参数中指定获取电影的哪些字段,然后不多不少地刚好获取这些字段。这样就算是有 10 个场景,服务端也不需要新增接口、新写代码,而客户端也不需要接收无用数据!

为什么要用 Apollo Federation

那么,Apollo Federation 又是什么呢?首先要说明,Apollo Federation 并不是 GraphQL 本身的一部分,而是 Apollo 公司针对 GraphQL 在微服务架构下应用所推出的一个增强工具。

但 Apollo Federation 和 GraphQL 的结合是这么完美,以至于在微服务架构下,没有人会想只用 GraphQL,不用 Apollo Federation!

那么常规的 GraphQL 在微服务架构下会遇到什么问题呢?

举例来说,推荐服务和内容服务是两个不同的微服务,对应两个不同的域(Domain),由两个不同的团队维护。每个团队各自都提供了一个接口:

推荐服务的接口可以返回推荐列表,包括每个电影的 ID;内容服务根据电影 ID 列表,可以返回每个电影的相关数据;

这个时候问题就来了:如果希望渲染推荐列表,那么即便推荐服务和内容服务的接口都是 GraphQL 接口,也至少要发两个请求!这就违背了 GraphQL “一个请求不多不少刚好拿到全部所需数据” 的核心思想!

(当然,这两个 GraphQL 请求不一定是客户端发送的,也可能是服务端有一个专门供客户端调用的服务(一般称为 BFF,Back-end for Front-end),把这些数据收集起来统一返回给客户端。)

而且这才只是涉及了两个微服务,如果一个请求涉及 3 个、4 个甚至更多微服务,对于客户端(或者 BFF)来说就更麻烦了。

这个时候 Apollo Federation 就派上用场了。Apollo Federation 分为两个部分:

第一个部分是协议:每个微服务必须按照这个协议,提供符合要求的 GraphQL 服务;第二个部分是 Apollo Federation Gateway,这是一个特殊的 GraphQL server,它在运行时会连接所有的微服务的 GraphQL 接口,然后为给调用者提供一个包含完整信息的 统一的 GraphQL 接口。这样一来,调用者只需要向 Gateway 发起查询,就可以获得全部所需数据!

其实 Apollo Federation 的原理也很简单,就是看你需要什么数据,然后分别到相应域的微服务中去拿,最后再拼接好了给你。虽然简单,但真自己写起来会很麻烦,Apollo Federation 替你省下了一大笔麻烦!

一个真实的案例

说了这么多,让我们看一个真实的例子吧!

我们公司这次把所有客户端用 SDUI 架构整个重写了一遍(参见初识 SDUI(Server-Driven UI,服务端驱动 UI)的同时,顺便也用上了 GraphQL 这个技术。

简单来说,客户端的一次请求的流程是这样的:

    客户端调用 BFF(解释见上面),典型的情况是每一个页面调用一次;BFF 会根据这一页面,写一个 GraphQL 查询,请求 Federation Gateway,把渲染该页面所需的全部数据都拿过来;BFF 根据这些数据,组装成页面上的各种组件,返回给客户端,客户端渲染这些组件;

当然了,步骤 1 和 3 在这里不重要,因为只有步骤 2 涉及到了 GraphQL。

我在搜索引擎团队,相当于一个域,有自己的微服务。作为一名开发者,我感觉切换到了 GraphQL 之后的开发体验好了很多!

在使用 GraphQL 之前,客户端会向我们请求搜索结果列表,我们需要返回很多内容相关的字段,包括标题、图片这些基础字段,还有很多其实用不上的冗余字段。

在切换到 GraphQL 之后,我们只需要返回一个内容 ID 的列表就可以了!BFF 会请求 Federation Gateway,而 Gateway 会向我们请求搜索结果的内容 ID 列表,然后再向内容服务的 GraphQL 接口请求每个内容 ID 对应的字段。

这样一来,开发效率就提高了很多,再也不用处理那些内容相关的返回字段了!

小结:什么样的团队适合使用 GraphQL

总的来说,GraphQL 更适合比较复杂的场景。如果你的使用场景很简单,对象的字段也不多,那么 REST 确实就够了。

在业务场景逐渐复杂之后,就可以考虑迁移到 GraphQL。其实 GraphQL 毕竟只不过是在 REST 上加了一层,所以之前的 REST 服务也没有白写,迁移也很简单。

如果是微服务架构的话,就可以考虑使用 Apollo Federation,其实也很简单,几乎不需要什么额外配置或者改动。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/5716832.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-17
下一篇 2022-12-17

发表评论

登录后才能评论

评论列表(0条)

保存