从模式拼接迁移
如何过渡到Apollo Federation
如果您有一个使用模式拼接的分布式图,请遵循本指南中的步骤将其迁移到使用Apollo Federation。
有关一个从模式拼接迁移到Apollo Federation受益的组织实例,请参见这篇博客文章。
步骤摘要
本指南描述了一组将架构逐步从拼接迁移到联盟的一组步骤。为此,我们依赖于联盟所需的变化完全向后兼容的事实。实现您的图部分的服务,也称为子图,可以在您的拼接网关和Apollo网关中使用。
建议您从修改现有的子图开始,以支持联盟规范,同时继续支持模式拼接。在此阶段,您可以与现有的拼接网关并行启动Apollo网关,并以增量、向后兼容的方式迁移子图之间的链。
以下是迁移到Apollo Federation的高级步骤:
- 为您的子图添加联盟支持。
- 通过注册将您的GraphQL模式注册。
- 启动一个Apollo Server实例作为网关。
- 将您模式拼接网关中的拼接逻辑迁移到您的子图。
- 将流量从模式拼接网关迁移到 Apollo Server 网关。
- 从您的联邦模式中移除模式拼接 字段,并完成迁移。
以下将详细描述每个步骤。
这个GitHub仓库展示了在从模式拼接迁移到 Apollo Federation 之前和之后的项目。
步骤 1:为您的子图添加联邦支持
您可以在不影响现有模式拼接架构的情况下,为您的 subgraphs 添加联邦支持。联邦支持与模式拼接完全兼容。
因此,我们建议您直接迁移 subgraphs,而不是创建替换的子图。这样做有助于您识别图形中存在的任何类型冲突。
使用 Apollo Server
如果您 subgraphs 使用 Apollo Server,可以通过安装 @apollo/subgraph
包来为它们添加联邦支持:
npm install @apollo/subgraph
然后使用 buildSubgraphSchema
函数来增强您的模式,以包含必要的 fields 支持联邦:
const { ApolloServer } = require('@apollo/server');const { buildSubgraphSchema } = require('@apollo/subgraph');const server = new ApolloServer({schema: buildSubgraphSchema([{typeDefs,resolvers,},]),});
除了 Apollo Server 之外使用 GraphQL 服务器
有几个由社区贡献的包,将这些包添加到其他GraphQL运行时中,以添加联邦支持。
步骤 2:将您的模式注册到 GraphQL 注册表
我们强烈建议您将所有GraphQL模式注册到一个外部注册表。此注册支持运行带有子图的'部分模式'网关。此外,它支持在子图级别跟踪更改,并保护图免受破坏组合的更改。
GraphOS还提供了一个免费的模式注册表,帮助您管理您的联合网关配置。您在启动时为数组提供一个 Studio API 密钥,这将引导网关以容错方式自动下载您的模式。
GraphOS还可以提供模式验证以确保您对子图所做的所有更改都与您的完整图兼容。
步骤 3:启动 Apollo Server 网关
在您注册了模式后,您可以从一个支持联邦的网关公开您的子图。Apollo Server的网关是一个查询规划器和执行器,处理传入的GraphQL请求,并将它们分解成在您的子图上执行的一组操作。
我们建议将Apollo Server网关与您现有的模式拼接网关一起设置。根据您的基础设施,您甚至可能希望在同一进程中运行这两个程序,以支持通过一个网关或另一个网关动态路由流量。
为了启用与管理配置结合使用GraphOS Studio,在启动您的Apollo Server网关时设置APOLLO_KEY
和APOLLO_GRAPH_REF
环境变量,不要向ApolloGateway
提供supergraphSDL
或serviceList
构造函数选项。有关详细信息,请参阅管理联邦文档。
您的网关设置完成后,您可以对其进行直接查询,这些查询会路由到正确的子图。
步骤 4:将连接逻辑移到您的子图中
在使用的模式连接网关中,您的连接逻辑通常位于网关本身中。然而,在联邦模型中,连接逻辑位于每个子图中。因此,您需要将连接逻辑从模式连接网关迁移到您的每个子图中。
以下是在迁移您的逻辑时的常见案例建议
- 片段:模式连接解析器中的片段通常转换为联邦模型中@key和@requires指令的组合。一般来说,把
@key
看作是完全标识一个实体的字段(们),只使用@requires
来表示额外的非识别信息。 - 过滤类型:当使用网关时,我们不推荐过滤出您暴露的架构中的类型。如果您想隐藏类型,请勿将其包括在您的子图已注册的架构中。
- 重命名类型:如果您目前在网关层面重命名类型,请在子图层面重命名这些类型。
- 转换字段:如果您目前在网关层面转换字段,请在子图层面转换这些字段。
向您的子图添加解析器
此时,您的子图支持联邦,但它们还需要能够解析在其它子图中定义的类型的扩展。
模式连接架构使用delegateToSchema函数在网关层面声明此逻辑,如下所示:
resolvers: {Reservation: {user: {fragment: `... on Reservation { userId }`,resolve: (parent, args, context, info) => {return info.mergeInfo.delegateToSchema({schema: userSchema,operation: 'query',fieldName: 'user',args: {id: parent.userId,},context,info,});},},},}
此解析器调用Query.user
在userSchema
上,以查找User
。它将用户添加到先前在网关中定义的Reservation.user
字段中。这段代码可以保留。您不需要从拼接网关中删除它。实际上,如果您这样做,拼接网关就会崩溃。
另一方面,联邦架构在子图级别定义其解析器。这些解析器依赖于实体,这些实体由一个唯一键标识。例如,预订子图必须将Reservation
类型定义为实体,以便其他子图可以扩展它。这些其他子图使用Reservation
's @key
字段来唯一标识特定实例:
type Reservation @key(fields: "id") {id: ID!...}
在用户子图中,您可以通过以下方式扩展Reservation
类型:
extend type Reservation @key(fields: "id") {id: ID! @externaluserId: ID! @externaluser: User @requires(fields: "userId")}
该user
字段表示它@requires
一个Reservation
's userId
字段,以识别创建了预订的用户。
然后,在用户子图中,您可以为Reservation.user添加一个解析器:
{Reservation: {user: ({ userId }) => {return lookupUser(userId);},}}
像这样的联邦解析器始终接收一个表示扩展实体实例的对象。该对象包括实体@key
字段,以及解析器的
例如,此Reservation.user
解析器接收预订的id
和userId。您可以使用userId
来查找相应的用户。
步骤 5:将流量从模式拼接网关转移到 Apollo Server 网关
到此为止,您的模式拼接网关和联邦网关都能够解析GraphQL操作。您现在可以开始将流量从模式拼接网关迁移到联邦网关。
请根据您的基础设施和应用程序的特点执行此迁移。
一些选项包括
- 在您的预发布环境中测试完整的迁移,以验证两个网关的行为是否相同
- 使用HTTP头或功能标志来迁移您的内部客户端,而不影响您的面向用户的客户端
第6步:从您的联邦模式中删除模式拼接字段
在您的图和入站流量完全迁移到使用您的联邦网关后,您可以从您的架构中删除所有拼接特定的逻辑。
现在,您可以开始修改现有的模式,以充分利用联邦提供的功能。这些功能包括