GraphQL 是一种用于 API 开发的查询语言,它允许客户端指定需要获取的数据结构,从而减少数据传输量并提高数据传输效率。GraphQL 的 Federation 特性则更进一步,它允许将多个 GraphQL API 合并成一个 API,使得客户端可以在不同的 API 之间无感知地查询数据。
本文将介绍 GraphQL Federation 的基本概念,以及如何使用该特性来合并多个 GraphQL API 并生成一个统一的 API。
什么是 GraphQL Federation?
在传统的方式下,一个完整的 GraphQL API 通常由一个 Schema 和一组 Resolver 组成。因为 Resolver 只能处理 Schema 中定义的对象和字段,所以一个单独的 Resolver 组合通常只能处理一个 GraphQL API。
GraphQL Federation 则提供了一种更加开放的方式,它将不同的 GraphQL API 分成许多小的 Schema 和 Resolver 组,每个小 Schema 可以定义自己的对象和字段,甚至可以自己开发处理器。使用 GraphQL Federation,我们可以将这些小的 Schema 组合在一起,从而生成一个统一的 API。
在 GraphQL Federation 模式下,每个小的 Schema 被称为 Service。每个 Service 必须实现一组特定的协议,以便与其他 Service 进行通信。具体来说,每个 Service 必须实现 @key 指令,@key 指令用于将关联字段暴露给其他 Service,从而实现 Service 之间的关联查询。
如何使用 GraphQL Federation?
下面我们将介绍如何使用 GraphQL Federation 来构建一个简单的电子商务系统 GraphQL API。
首先,我们需要定义一个 GraphQL Schema,该 Schema 定义了所有商品的对象和字段:
-- -------------------- ---- ------- ---- ------- ------------ ------ - ---- --- ----- ------- ------------ ------ ------ ------ - ---- ----- - ------------ ----- ------- -
在该 Schema 中,我们定义了一个名为 Product 的对象,它具有四个字段:sku、name、description 和 price。@key 指令用于将 sku 字段设置为关键字,以便在其他 Service 中访问该字段。
接下来,我们需要将该 Schema 转换为一个 Service。此时,在 GraphQL Federation 中,一个 Service 通常由两个部分组成:一个 Schema 和一组 Resolver。
Card Service 代码如下所示:
-- -------------------- ---- ------- -- --------------- ----- - ------------- --- - - ------------------------- ----- - -------------------- - - ------------------------------ ----- -------- - ---- ------ ---- ------- ------------ ------ - ---- --- --------- -------- ------- - ------ ---- ----- - ------------------- ----- ------- - -- ----- --------- - - -------- - ----------------------------- - ------ - ---- -------------- -------- ------------- - ---- -- -- -- ------ - ----------------- - --- -- - ------ - ----------- ---------- --- -- -- -- -- ----- ------ - --- -------------- ------- ----------------------- --------- --------- --- --- --------------- ----- ---- ---------- --- -- -- - --------------- ---- ------- ----- -- --------- ---
在此代码中,我们定义了一个名为 Card Service 的 Service,该 Service 扩展了 Product 类型,并添加了一个新的字段 inStock。该字段表示产品是否在库存中。我们还定义一个新的查询 productInStock,它接收一个 sku 参数并返回匹配该 sku 的产品,并将 inStock 字段设置为该产品是否有库存。
注意,在 Card Service 中,我们通过将 @external 指令应用到 sku 字段来表明这是与其他 Service 分享的字段。由于在 Card Service 中不会定义 Product 类型,因此我们必须通过外部解析器引用它。
接下来,我们还需要创建一个用于查询 Card Service 的 Schema,并将它添加到当前的 Schema 中:
-- -------------------- ---- ------- ----- -------- - ---- ------ ---- ------- ------------ ------ - ---- --- --------- -------- ------- ----------------- ------ ----------- ----- ---- - ---- ---- ------------ ------------- - ----------- --- ------ ------------ ------ ------ - ---- -------- - -------- -------- --------- ---- ------ ------ --------- ------- - ------ ---- ----- - -------- ----- ---- - -- ----- --------- - - -------- - ----- ------------- - ----- -- - ------------ - ----------- - -- - ----- ----- - ----- ------------------------------------- ------- ----- ----- - ------------- ----- - ------ -------- -- -- --- - ----- - --------- - -- ------ - ----------- ------------ ------ ------ -- -- -- --------- - ------------- -- - ------------ - -------------- - -- - ------ ------------------------------------------- -- ----------- - ------ ----------- -- -- ----- - ----------------------------- - ------------ - ----------- - -- - ------ ---------------------------------- -- -- ------ - ----- ------- - -- -- - ------------ - ----------- - -- - ------ ------------------------ -- -- -- ----- ------ - --- -------------- ------- ----------------------- --------- --------- ---- --- --------------- ----- ---- ---------- --- -- -- - --------------- ------- ------- ----- -- --------- ---
在此代码中,我们定义了一个名为 Card 的类型,它表示用户购物车中的所有产品。该类型具有三个字段:productSku、items 和 total。productSku 表示当前购物车中的产品 sku,items 表示当前购物车中的所有商品,total 表示当前购物车中商品的总价。
我们还定义了一个名为 CartItem 的类型,表示购物车中的单个商品。Cart 商品具有四个字段:product、quantity、price 和 currency。product 字段表示该商品的详细信息(如名称、描述、价格等),quantity 字段表示购物车中的商品数量,price 字段表示该商品的单价,currency 表示货币单位。
在我们的 Resolver 中,我们通过 ProductService 和 CardService 对 Product 和 Card 类型进行解析。我们的 Gateway 逻辑将处理来自客户端的所有查询,并将其路由到相应的 Service。
总结
GraphQL Federation 是一种实现微服务实践的好方式,它使得将单一 API 拆分多个部分并实现独立扩展变得容易。当您的应用程序需要更加定制化的查询、更灵活的数据结构时,它是一个不错的选择。通过上面我们的示例代码的学习,总结出其流程,对于学习和使用 GraphQL Federation 有很大帮助。
来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/645dd089968c7c53b00312e1