现有对外GraphQL服务能否与GraphQL Federation并行运行
答案
完全可以在同一份代码库中同时运行非联邦模式、联邦模式两个Apollo Server实例,不需要维护两套独立代码,也能兼容短期内无法迁移的老客户端。
具体实现思路
- 首先抽离所有公共核心逻辑:把业务相关的typeDefs、resolver、上下文鉴权逻辑、数据源连接、通用工具方法全部抽成独立的公共模块,两套服务实例直接引用这部分内容,从根源上避免重复编码。
- 保留原有非联邦实例:初始化逻辑和现有服务完全一致,继续沿用原来的访问端口、路由路径,老客户端的所有调用不需要做任何修改,无感知兼容现有流量。
- 新增联邦子图实例:基于同一份公共核心逻辑,引入联邦相关依赖,用
buildSubgraphSchema方法包装生成符合联邦规范的子图schema即可,不需要改动任何核心业务代码。这个实例可以单独监听端口,也可以和原有实例挂在同一个HTTP服务下通过路径分流。 - 联邦专属逻辑做隔离:联邦需要的
@key、@external等专用指令、跨子图的字段扩展逻辑单独存为独立schema文件,只有初始化联邦子图实例的时候才加载这部分内容,绝对不要混入非联邦实例的schema中,避免老客户端拉取schema时出现指令不识别的报错。
最简实现参考
const { ApolloServer } = require('@apollo/server'); const { buildSubgraphSchema } = require('@apollo/subgraph'); const http = require('http'); // 两套实例共用的核心业务逻辑 const coreTypeDefs = require('./core/schema'); const coreResolvers = require('./core/resolvers'); const createContext = require('./core/context'); // 仅联邦实例使用的schema扩展(@key指令、跨子图字段等) const federationExtendTypeDefs = require('./federation/schema-extend'); // 初始化原有非联邦服务实例 const vanillaServer = new ApolloServer({ typeDefs: coreTypeDefs, resolvers: coreResolvers, }); await vanillaServer.start(); // 初始化联邦子图服务实例 const federatedServer = new ApolloServer({ schema: buildSubgraphSchema({ typeDefs: [coreTypeDefs, federationExtendTypeDefs], resolvers: coreResolvers, }) }); await federatedServer.start(); // 同一个HTTP服务按路径分流,无需开放多端口 const httpServer = http.createServer(async (req, res) => { const context = await createContext(req, res); if (req.url.startsWith('/graphql')) { // 原有入口,给未迁移的老客户端使用 await vanillaServer.executeHTTPGraphQLRequest({ req, res, context }); } else if (req.url.startsWith('/federation/subgraph')) { // 联邦子图入口,给联邦网关调用 await federatedServer.executeHTTPGraphQLRequest({ req, res, context }); } else { res.statusCode = 404; res.end('Not Found'); } }); httpServer.listen(4000, () => { console.log('服务启动完成'); });
落地提示
- 两个实例可以完全共享数据库连接、缓存实例、鉴权逻辑等公共资源,不会产生额外的资源浪费。
- 上线初期可以先把联邦子图接入网关做内部验证,等所有客户端逐步完成联邦网关的迁移适配后,再下线非联邦实例即可,整个迁移过程没有强制时间窗口,不会影响线上业务。
- 日常迭代只需要修改公共核心模块的代码,两个实例会同步生效,不存在两套代码逻辑不一致的问题。
内容的提问来源于stack exchange,提问作者Karthik Gowda
相关产品推荐
相关产品推荐

