GraphQL 联邦
作为经典单体架构(通常被称为微服务)的一种替代设计方法,联邦强调将复杂的系统分解为更小、可独立管理的组件。在某些方面,GraphQL 联邦就像是 GraphQL 的微服务——这是一种在 GraphQL 生态系统中特别引起共鸣的架构模式。
在 Apollo GraphQL 于 2019 年引入 Apollo Federation 之后,GraphQL 联邦获得了广泛的采用。他们的实现已成为 GraphQL 社区的参考点,帮助确立了联邦作为在 GraphQL 生态系统中构建分布式图谱的标准架构模式。
随着越来越多的公司和开发人员看到构建分布式 GraphQL Schema 的好处,GraphQL 生态系统正朝着联邦模式的标准化发展。GraphQL 基金会的 复合 Schema 工作组(包括来自 Apollo GraphQL、ChilliCream、Graphile、Hasura、Netflix 和 The Guild 等业内各种组织的工程师)正在积极致力于创建 GraphQL 联邦的官方规范。这项工作旨在标准化跨分布式系统组合和执行 GraphQL 服务的方式,同时确保为创新和不同实现留出空间。
什么是联邦?
从架构上讲,联邦是一种组织和管理分布式系统的方法。其核心在于,联邦允许自主组件协同工作,同时保持其独立性。把它想象成一个联邦政府体系:各个州在保持自身主权的同时,为了共同的关注点在一个中央权威下进行合作。
在软件架构中,联邦使组织能够
- 将责任分配给独立的团队
- 独立扩展不同的组件
- 在不同领域之间保持清晰的边界
- 实现自主开发和部署
- 减少单点故障
想想你在网站上看到的“使用 Google 登录”或“使用 Facebook 登录”按钮。这就是联邦的实际应用:你可以使用你的 Google 或 Facebook 账户登录许多不同的网站,即使每家公司都单独管理自己的登录系统。
什么是联邦式 GraphQL?
GraphQL 联邦将这些原则应用于 GraphQL API。它使组织能够从多个独立服务(通常称为子图)构建统一的 GraphQL Schema,每个服务负责应用程序数据图谱的一部分。
考虑一个电子商务平台:你可能有负责产品、用户账户和订单处理的独立团队。通过 GraphQL 联邦,每个团队都可以
- 定义自己的 GraphQL Schema
- 独立部署和扩展其服务
- 在没有紧密耦合的情况下为统一的 GraphQL API 做贡献
- 维护对其领域特定逻辑的所有权
神奇之处在于一个充当中央协调器的联邦网关,它将这些单独的 Schema 组合成一个统一的 Schema,供客户端查询。
GraphQL 联邦的工作原理
联邦过程涉及几个关键组件
- 子图 (Subgraphs):定义自己的 GraphQL Schema 和解析器的独立服务
- 网关 (Gateway):位于客户端和你的联邦服务之间的专用服务
- Schema 组合 (Schema composition):在解析它们之间的引用时合并 Schema 的过程,通常由 Schema 注册中心处理。
type Product @key(fields: "id") {
id: ID!
title: String!
price: Float!
inStock: Boolean!
}Schema 组合
让我们用更多细节和示例来分解 GraphQL 联邦中的 Schema 组合。Schema 组合是将多个子图 Schema 合并为一个统一 Schema 的过程。然而,它比简单地合并 Schema 复杂,因为它需要处理引用、检测不兼容性,并确保跨服务和子图的类型正确连接。
根据我们之前提供的示例,以下是 GraphQL 客户端将看到并可以查询的统一 Schema
type Query {
user(id: ID!): User
}
type User {
id: ID!
name: String!
email: String
orders: [Order!]!
}
type Order {
id: ID!
products: [Product!]!
total: Float!
}
type Product {
id: ID!
title: String!
price: Float!
inStock: Boolean!
}这个统一的 Schema 结合了所有三个子图(用户、订单和产品)的类型和字段,使客户端能够无缝地跨这些领域进行查询。
网关
联邦网关是你分布式数据图谱的入口点。它向客户端呈现统一的 GraphQL 端点,并处理将查询路由到适当的子图并组装结果的复杂性,并且通常提供缓存和性能优化。
以以下查询为例
query {
user(id: "123") {
# Resolved by Users subgraph
name
orders {
# Resolved by Orders subgraph
id
products {
# Resolved by Products subgraph
title
price
}
}
}
}网关会将查询的不同部分路由到适当的子图,收集结果,并将它们组装成客户端可以使用的单个响应。
GraphQL 联邦的优势
领域驱动开发
团队可以独立地开发他们的服务,同时为统一的 API 做贡献。这种自主性加速了开发并减少了协调开销。
服务完整性保护
Schema 组合步骤通过确保单个子图中的更改不会与其他子图冲突,来验证服务之间的集成。
可扩展性和性能
子图和服务可以根据其特定要求独立扩展。产品目录可能需要与订单处理系统不同的扩展特性。
单一、统一的 API
多亏了 GraphQL,客户端获得了一个具有跨多个子图的统一 Schema 的单一端点。分布式系统的复杂性被隐藏了。网关确保每个查询都能到达其目的地并返回正确的数据。
GraphQL 联邦适合你吗?
GraphQL 联邦自然地与领域驱动设计 (DDD) 原则保持一致,它允许团队维护其领域的清晰边界,同时通过 GraphQL Schema 保持明确的集成点。对于需要在不同团队独立开发 GraphQL API 不同部分,并具有使用不同技术和编程语言的灵活性的组织来说,它尤其有价值。
然而,实施联邦需要大量的基础设施支持,包括一个专门的团队来管理网关、Schema 注册中心,以帮助将子图连接到联邦 API 并指导团队最佳实践。
在采用联邦之前,至关重要的是要考虑你的组织是否真正需要这种程度的复杂性。你可以从单体设置开始,随着需求的演变再过渡到联邦,而不是过早地实施它。
Meta(前身为 Facebook),即 GraphQL 的诞生地,自 2012 年以来一直使用单体 GraphQL API。然而,像 Netflix、Expedia Group、沃尔沃 (Volvo) 和 Booking 这样的公司已经采用了联邦模式,以更好地与其组织结构和微服务架构保持一致。
正如你所见,一些全球最大的行业领导者已经成功地联邦化了他们的 GraphQL API,证明它在非同寻常的规模下对生产应用程序可靠地工作。
开始使用 GraphQL 联邦
如果你正考虑采用 GraphQL 联邦,以下是一些入门步骤
- 识别服务边界:在应用程序的不同领域之间定义清晰的边界
- 设计 Schema:创建反映这些边界的 Schema,同时考虑它们将如何交互
- 实现子图:构建实现其 Schema 部分的独立服务
- 设置网关:部署一个联邦网关来组合和提供统一的 Schema
- 使用 Schema 注册中心:管理 Schema 组合和验证,以确保跨子图的完整性
在从单体式 GraphQL API 迁移到联邦式 GraphQL API 时,最简单的起点是将你现有的 Schema 作为你的第一个子图。从那里,你可以遵循上述步骤,将你的 Schema 逐渐分解成更小的部分。
常见的 GraphQL over HTTP 错误
了解常见的 'graphql-http' 错误以及如何调试它们。