GraphQL 自诞生以来就被寄予厚望,被认为是一种有望替代 REST 的新一代服务端调用方式。
而 Apollo Federation 这个工具是对 GraphQL 的一种增强,让 GraphQL 能够更好地应用在微服务架构下。
下面就来简单分析一下,为什么要使用 GraphQL / Apollo Federation?
那么,GraphQL 比 REST 好在哪里呢?
举个例子:假设你想查询一部电影的相关信息,至少有两种情况:
如果只用一个 REST 接口满足两种场景,永远返回全部数据(现实中应该没人这么干),那么在场景 1 中,客户端就会收到大量无用的数据;
如果用两个 REST 接口分别供这两种场景调用(现实中应该会是这样),那么对服务提供方和调用方来说维护成本都很高。假如某个场景发生变化,或者新增了场景,那么服务端还需要修改或者新增接口;
还有一种 REST 的思路是,在请求参数中指定需要返回哪些数据,或者指定当前是哪种场景。但这样还是会提高维护成本,而且既然都想这么做了,为啥不直接用 GraphQL 呢??毕竟 GraphQL 其实就是在 REST 上增加了一层,来自动化地实现“指定返回哪些数据”的功能呀!
相比之下,使用 GraphQL 的好处就显而易见了:只需要一个接口,客户端在查询参数中指定获取电影的哪些字段,然后不多不少地刚好获取这些字段。这样就算是有 10 个场景,服务端也不需要新增接口、新写代码,而客户端也不需要接收无用数据!
那么,Apollo Federation 又是什么呢?首先要说明,Apollo Federation 并不是 GraphQL 本身的一部分,而是 Apollo 公司针对 GraphQL 在微服务架构下应用所推出的一个增强工具。
但 Apollo Federation 和 GraphQL 的结合是这么完美,以至于在微服务架构下,没有人会想只用 GraphQL,不用 Apollo Federation!
那么常规的 GraphQL 在微服务架构下会遇到什么问题呢?
举例来说,推荐服务和内容服务是两个不同的微服务,对应两个不同的域(Domain),由两个不同的团队维护。每个团队各自都提供了一个接口:
这个时候问题就来了:如果希望渲染推荐列表,那么即便推荐服务和内容服务的接口都是 GraphQL 接口,也至少要发两个请求!这就违背了 GraphQL “一个请求不多不少刚好拿到全部所需数据” 的核心思想!
(当然,这两个 GraphQL 请求不一定是客户端发送的,也可能是服务端有一个专门供客户端调用的服务(一般称为 BFF,Back-end for Front-end),把这些数据收集起来统一返回给客户端。)
而且这才只是涉及了两个微服务,如果一个请求涉及 3 个、4 个甚至更多微服务,对于客户端(或者 BFF)来说就更麻烦了。
这个时候 Apollo Federation 就派上用场了。Apollo Federation 分为两个部分:
其实 Apollo Federation 的原理也很简单,就是看你需要什么数据,然后分别到相应域的微服务中去拿,最后再拼接好了给你。虽然简单,但真自己写起来会很麻烦,Apollo Federation 替你省下了一大笔麻烦!
说了这么多,让我们看一个真实的例子吧!
我们公司这次把所有客户端用 SDUI 架构整个重写了一遍(参见初识 SDUI(Server-Driven UI,服务端驱动 UI)的同时,顺便也用上了 GraphQL 这个技术。
简单来说,客户端的一次请求的流程是这样的:
当然了,步骤 1 和 3 在这里不重要,因为只有步骤 2 涉及到了 GraphQL。
我在搜索引擎团队,相当于一个域,有自己的微服务。作为一名开发者,我感觉切换到了 GraphQL 之后的开发体验好了很多!
在使用 GraphQL 之前,客户端会向我们请求搜索结果列表,我们需要返回很多内容相关的字段,包括标题、图片这些基础字段,还有很多其实用不上的冗余字段。
在切换到 GraphQL 之后,我们只需要返回一个内容 ID 的列表就可以了!BFF 会请求 Federation Gateway,而 Gateway 会向我们请求搜索结果的内容 ID 列表,然后再向内容服务的 GraphQL 接口请求每个内容 ID 对应的字段。
这样一来,开发效率就提高了很多,再也不用处理那些内容相关的返回字段了!
总的来说,GraphQL 更适合比较复杂的场景。如果你的使用场景很简单,对象的字段也不多,那么 REST 确实就够了。
在业务场景逐渐复杂之后,就可以考虑迁移到 GraphQL。其实 GraphQL 毕竟只不过是在 REST 上加了一层,所以之前的 REST 服务也没有白写,迁移也很简单。
如果是微服务架构的话,就可以考虑使用 Apollo Federation,其实也很简单,几乎不需要什么额外配置或者改动。