如何为Apollo Gateway添加自定义解析器以编排子图调用?
关于Apollo网关自定义解析器跨子图调用的解决方案
明确说:不需要用fetch直接调用子图,Apollo Gateway本身提供了内置方法,可以复用已配置的子图客户端,不用重复处理认证、地址等配置,更简洁可靠。
具体实现方式
你可以在自定义解析器中通过网关实例获取子图的客户端,发起GraphQL请求,核心是利用gateway.loadService()方法加载已配置的子图,再调用其execute方法执行查询/突变。
调整后的示例代码
const { ApolloGateway, ApolloServer } = require('@apollo/gateway'); const gateway = new ApolloGateway({ serviceList: [ { name: 'products', url: 'https://products-service.dev/graphql' }, { name: 'reviews', url: 'https://reviews-service.dev/graphql' } ], introspectionHeaders: { Authorization: 'Bearer abc123' } }); // 创建Apollo服务器并添加自定义逻辑 const server = new ApolloServer({ gateway, // 自定义类型定义,声明需要的突变 typeDefs: ` type Mutation { doSomeThing: String } `, resolvers: { Mutation: { doSomeThing: async (_, __, context) => { // 1. 加载products子图客户端,调用接口获取数据 const productsService = await gateway.loadService('products'); const productResult = await productsService.execute({ query: ` query GetTargetProduct { product(id: "target-id") { id reviewRelationId } } `, // 传递网关请求的headers,保证子图能拿到认证等上下文信息 context: { headers: context.req.headers } }); const reviewId = productResult.data.product.reviewRelationId; // 2. 用products的结果加载reviews子图客户端,发起调用 const reviewsService = await gateway.loadService('reviews'); const reviewResult = await reviewsService.execute({ query: ` mutation SyncReview($reviewId: ID!, $productId: ID!) { syncReview(reviewId: $reviewId, productId: $productId) { id status } } `, variables: { reviewId, productId: productResult.data.product.id }, context: { headers: context.req.headers } }); return `跨子图操作完成:${reviewResult.data.syncReview.status}`; } } } }); server.listen().then(({ url }) => { console.log(`🚀 网关服务运行在 ${url}`); });
关键细节说明
- 复用网关配置:通过
loadService获取的子图客户端,会自动继承网关中配置的URL、认证头、超时等参数,不用重复编写配置逻辑,避免出现不一致问题。 - 上下文传递:将网关请求的headers传递给子图调用,确保认证、链路追踪等上下文信息能正常透传到子图服务。
- 封装逻辑优势:网关提供的
execute方法已经封装了GraphQL请求的格式处理、错误捕获等逻辑,比直接用fetch手动实现更稳定、更易维护。
内容的提问来源于stack exchange,提问作者Stretch0
相关产品推荐
相关产品推荐

