精进之路  

How Netflix Scales its API with GraphQL Federation (Part 1)

https://netflixtechblog.com/how-netflix-scales-its-api-with-graphql-federation-part-1-ae3557c187e2

unfederated graphql

cons: 微服务的独立开发的好处被削弱了,统一的 graphql 层成了单点依赖,不方便快速迭代。且由一个统一的小团队来维护是有难度的。

转向 federated

  • 首先是 federated type. 可以在一处定义,多处被 extend. 此时 resolve 这个 type 的 field 就被 gateway delegate 到其对应的 owning domain service.

核心架构组件

  • gateway team
    • graphql gateway
      • 给 consumer 提供 query 服务。它接受一个 query, 拆解成 sub queries, 形成 query plan, 然后通过把调用 proxy 到下游的 DGS 的方式执行 query plan.
    • schema registry
      • 暴露 schemas 的 CRUD api,给到开发者工具,以及 CI/CD pipelines.
      • 负责每个 DGS 的 schema 以及合并的 schema 的校验
      • 组合一个统一的 schema,提供给 gateway
  • domain team(s)
    • DGS (domain graph service). 包含 resolver
    • microservice

主要技术细节

  1. schema 的组合

当 DGS 提交新的 schema 时,schema registry 会检查:

  • 新 schema 是否为 valid 的 graphql schema (合法性)
  • 新 schema 是否能和已有的其他 schemas 无缝组合,形成一个 valid 的新 schema (兼容性)
  • 新 schema 是否向前兼容
  1. query planning and execution

composed schema + client query = query plan.

在创建 query plan 时,会首先判断每个 field 是由哪个 DGS own 的,从而生成对应的 sub query.
然后,还会根据依赖关系,判断出哪些 sub query 可以并发执行,哪些有先后顺序。

  1. Entity resolver
  • 所有定义或扩展了 Movie 类型的 DGS 都要就一个或多个主键 fields 达成一致,如 movieId. 为此,Apollo 引入了 @key directive.
  • DGSs 需要为一个通用的 query field _entities 实现 resolver. 该 field 返回当前 DGS 里所有的 federated types. Gateway 使用 movieID 在 _entities 中查找对应的 Movie.

Part 2

https://netflixtechblog.com/how-netflix-scales-its-api-with-graphql-federation-part-2-bbe71aaec44a

Netflix 用 Kotlin 实现了 graphql gateway 和 schema registry.

schema registry 中,储存 schema changes 使用了一个实现了 event sourcing 的,基于 Casandra 数据库的内部库。

schema registry 还和 ci/cd 系统做了集成,以便可以自动为 DSGs 配置云上的网络。

graphql 自己的学习曲线

一些其他的 graphql hot topics

  • pagination
  • error handling
  • nullability
  • naming convensions

DSG Frameworks and Developer Tools

基于 graphql java 以及 spring boot 创建了 DSG Framework. 其功能:

  • 实现了所有为了在生产环境跑一个 graphql service 所必要的 cross cutting concerns
  • 同时允许 developer 方便的实现 resolvers
  • 实现了推送 schema 到 schema registry 的 robust tooling
  • 自助的 UI,可以浏览不同 DSG 的 schemas.

Schema Governance

有一个 dedicated Data Architect. 专门聚焦 data modeling,并在各部门之间协调。

goal 是要构建一个反应 domain 的 schema, 而不是 db model.
那么 ui 开发就应该不需要构建自己的 BFF,而是要帮助构建适合他们需要的 schema.

弃用 field 可以使用 deprecated 功能. 并且可以跟踪 field 的使用情况。一旦某个 feild 不再被使用,就可以做一个向后不兼容的变更,将它从 schema 中去除。

使用了 schema-first approach 去设计,而不是从 gRPC API 的 Protobuf 对象直接生成。
这样可以得到更干净的设计。即使在有些场景需要 graphql resolver map 到 gRPC calls,这些多余的 boilerplate 相对于 graphql api 的长期灵活性来说,还是有必要的。

Observability

  • alerting. 出现问题时及时报警
  • discovery. 方便的发现是什么不工作了
  • diagnosis. 诊断为什么不工作

metrics:

  • mean time to resolution (MTTR)
  • SLO/SLI (service level objectives and indicators)

集成了以下工具

  • 内部工具 Edgar:基于 Zipkin 分布式追踪,集成了 Gateway 和 DGS 的架构组件
  • TellTale: 应用监控工具

graphql 几乎每个请求的响应都是 200,而自定义错误在特定的 error 区块。
可以提取这些错误信息,发送到 metrics server Atlas.

关键点:

  • 错误信息采集
  • 分布式跟踪结果通过 timeline view 呈现
  • correlated logs

Securing the Federated Graph

Authentication

限制 graphql gateway 的 access 为仅允许登录后的 caller 访问;
graph introspection 仅限内部开发人员。

Authorization

将此职责 delegate 给了每个 DSG owner.

DSG 开发可以选择自己合适的授权方案。简单的方法是在 resolver 上配置 @Secured annotation.
复杂一点可以在 resolver 或者下游的系统里去实现。

Architecture for Failure

federation gateway 是故障单点,所以需要考虑高可用。为了保证 gateway 层是 resilient 的,一些设计原则如下:

  • single purpose. 减少 scope, 仅聚焦在解析 query, 构建和执行查询计划上。
  • stateless service. 严格的执行无状态设计,这样,就可以同时跑多个 gateway 实例。任意一个 gateway 都可以执行任何一个请求。并且,在上生产之前严格的测试。
  • demand controlled. rate limit, 并且做静态查询成本计算,拒绝特别耗资源的查询。
  • multi-region. 将 gateway 部署到了世界各个 region 的 AWS 上,避免爆发性的流量,同时,出问题时也方便做 fail over 切换。
  • shared by functionality. 布署 gateway 的多个不同功能的 shards. 比如:query 和 mutation 一般是短时间的操作;而 subscription 需要长时间占有连接。分片的话,就可以在 subscription 如果耗尽连接资源的时候,query 和 mutation 的可用性不受影响。
posted on 2022-08-08 02:11  Optimus_Prime  阅读(101)  评论(0)    收藏  举报