InfoQ|GraphQL两年实战避坑经验( 二 )


实践中 , 我们组合使用了上面两种方法 。 但现在我们面对一个新的问题 。 当前并非所有的变更都可通过 Public API 访问 , 因此在更新支付的状态时需要直接调用 Payment API 。 这对于变更不存在问题 , 但并不适用于所有的查询 , 因为父对象和子对象只是在 Public API 做拼接 。 为解决这个问题 , 我们需要再次重新编排配置 , 如下图所示:
InfoQ|GraphQL两年实战避坑经验
本文插图

这里 , 我们新建了一个 Gateway API , 负责拼接所有 Schema 。 而 Public API 只拼接 Gateway API , 并移除所有前端无需访问的查询和变更 。 这样 , Gateway 可与后端服务部署在同一网络 , 后端在进行查询和变更时可直接使用 Gateway API 。
查询分页(Paginated)
一些情况下 , 实现 查询分页 很有必要 。 我们采用了基于游标的方法 , 实践中很好用 。 需要获取 Product 时 , 可使用如下查询:
products(first: 5, after: "cursor") {edges {node {identifier}}}
但是 , 由于我们更改了 Schema , 在获取 Product 对应的 Order 时会生成分页结构:
order {products(first: 5, after: "cursor") {edges {node {identifier}}}}
但是这里我们并不需要分页结构 , 因为给定 Order 的 Product 数量并不多 。 针对该问题 , 我们考虑分别编写两个查询 , 一个实现了分页 , 另一个则不考虑分页 。 另一个做法是针对拼接 Product 到 Order 的情况 , 使用 Schema 包装(Schema Wrapping)移除分页 。 Schema 包装是一个非常强大的方法 , 尤其是针对同一 API 种拼接了所有远程 Schema 的情况 。 详细信息 , 参见 Schema 包装的官方文档 。
https://www.graphql-tools.com/docs/schema-wrapping/
一些建议
上面我们列举了部分主要问题 。 下面给出一些有助于构建可维护 GraphQL API 的小建议:
类型和枚举的命名必须唯一 。 例如 , 如果需要对 Product 添加一个状态 , 建议命名为 ProductStatus , 而不要直接使用 Status , 以免出现类型冲突问题 。
建议在查询中添加过滤 , 以免额外单独编写查询 。 推荐一个 很好的查询实现例子 , 访问页面右侧的“doc”选项卡, 并搜索 assetFilter 。
对查询和变更定义自己的命名规则 , 以简化对查询和变更的查找 。
在使用查询分页时 , 设置默认值和最大上限 。 以免他人运行 API 时导致崩溃 。
推荐使用 GraphQL Voyager , 可生成对 Schema 所有查询、变更、关系的概览图 。
参考阅读:
https://medium.com/better-programming/2-years-of-graphql-in-production-a1a6dbaddbda
InfoQ 读者交流群上线啦!各位小伙伴可以扫描下方二维码 , 添加 InfoQ 小助手 , 回复关键字“ 进群 ”申请入群 。 大家可以和 InfoQ 读者一起畅所欲言 , 和编辑们零距离接触 , 超值的技术礼包等你领取, 还有超值活动等你参加 , 快来加入我们吧!
【InfoQ|GraphQL两年实战避坑经验】点个在看少个 bug


推荐阅读