InfoQGraphQL两年实战避坑经验


InfoQGraphQL两年实战避坑经验
本文插图
作者 | Stein Janssen
译者 | 盖磊
策划 | 蔡芳芳
本文作者分享了在生产环境中使用 GraphQL 的一些经验和解决方法 , 并给出了一些构建实用 GraphQL 查询和变更(Mutation)的建议 。
本文最初发布于 Medium , 经原作者 Stein Janssen 授权由 InfoQ 中文站翻译并分享 。
GraphQL 已得到广泛认可并日益流行 。 我们在使用中遇到了一些非常有挑战性的问题 , 值得撰文分享 。 本文将使用一个示例配置来阐释问题 , 并给出相应的解决方法 。
InfoQGraphQL两年实战避坑经验
本文插图
本文作者使用 GraphQL Voyager 生成的关系概览图
首先谈谈我们为什么会选择 GraphQL?
无需操心如何更新文档 , 所有的查询(Query)和变更会自动形成文档 。
无需获取整个数据集 , 我们可以编写仅仅返回所请求数据的查询 。
对前端提供统一的访问点 。 从数十个不同 API 中获取数据并非易事 。 GraphQL 支持开发人员将所有 API 进行拼接(Stitching) 。
拼接(Stitching)
拼接(Stitching)让我们可以从同一端点获取所有数据 。 这听上去不错 , 但它也会导致一些非常棘手的问题 。 举例说明:
InfoQGraphQL两年实战避坑经验
本文插图
如上图所示 , 一个前端与 Public API 通信 。 Public API 拼接了 Order API , 后者又拼接了 Product API 。 前端唯一能访问的是 Public API 。 看上去这种链式拼接方式并没有太大的问题 , 但是在面对数十层级的 API 拼接时 , 应用发布将成为一场灾难 。
问题出在哪里?一旦 Product API 的 Schema 发生更改 , 那么需要依次重新启动 Order 和 Public API 才能重新加载 Schema 。 GraphQL Schema 每次更新时 , 都必须重新启动多个 API 。 这非常繁琐 。
另一个可能出现的问题是 , 如果应用需要逆链反向查询 , 而非顺链而下查询 , 这时拼接无法工作 。 例如从 Product 访问 Order , 由于 Order API 需要加载 Product 的 Schema , 因此只有在 Product API 运行时才能启动 Order API 。
这意味着 , 虽然可以获取属于给定 Order 的 Product:
order {identifierproducts {identifier}}
但无法获取给定 Product 所在的 Order:
products {identifierorder {identifier}}
为解决这个问题 , 我们需要重新拼接 API 。 我们可以让 Public 负责加载所有的 Schema 。 这样只需重启该 API , 即可加载所有 Schema 。
InfoQGraphQL两年实战避坑经验
本文插图
鉴于现在 Public API 获取所有的 Schema , 我们可以添加处理 order 属性的代码 , 扩展 Product 的 Schema 。 这样 , 我们就可以通过查询 Product 获取 Order 信息 。 扩展 Schema 的详细做法 , 参见 Apollo 文档 。
https://www.apollographql.com/docs/apollo-server/federation/entities/#extending
现在 , 我们并不需要通过 Public API 获得所有查询和变更的访问权 。 例如 , 我们并不想让客户能够通过触发变更去更改支付的状态 。 对此 , 一种解决方法是过滤掉特定查询和变更 。 具体而言 , 应用遍历 Schema 中所有的查询和变更 , 并与给定的列表做对比 。 如果查询存在于列表中 , 则设为可见 。 如果不在列表中 , 就从 Schema 中移除 。 另一个解决方法是添加中间件 , 由中间件检查当前用户是否有权限触发特定的查询和变更 。