You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ApolloGateway无法连接GraphQL Express服务问题求助

Apollo Gateway 连接 Product-Service 400 Bad Request 问题排查

问题重现

网关启动代码:

export const server = async () => {
  const app = express();
  const services = [ { name: "product-service", url: "http://localhost:4001/graphql" }];
  const availableServices: any[] = [];

  const gateway = new ApolloGateway({
    serviceList: services,
    buildService: ({ name, url }) => {
      return new RemoteGraphQLDataSource({
        url,
      });
    },
  });

  const server = new ApolloServer({
    subscriptions: false,
    gateway,
  });

  await server.start();
  server.applyMiddleware({ app });

  return app.listen(3000);
};

Product-Service 启动代码:

export const server = async () => {
  const schema = await buildSchema({
    resolvers: [__dirname + "/api/**/*.resolver.ts"],
    emitSchemaFile: path.resolve(__dirname, `../schema.gql`),
    authChecker: authChecker,
  });

  const app = express();

  const server = new ApolloServer({
    schema,
    context: (ctx: Context) => {
      const context = ctx;
      return context;
    },
  });

  await server.start();

  server.applyMiddleware({
    app,
  });

  return app.listen(4001);
};

报错信息:

Error checking for changes to service definitions: Couldn't load service definitions for "product-service" at http://localhost:4001/graphql: 400: Bad Request

排查步骤

1. 确认子服务是否开启 Introspection 接口

Apollo Gateway 依赖 GraphQL 的 introspection 查询获取子服务 Schema,若子服务禁用该功能会直接返回 400 错误:

  • 在 Product-Service 的 ApolloServer 配置中显式开启 introspection(开发环境默认开启,但生产环境或手动配置可能关闭):
    const server = new ApolloServer({
      schema,
      context: (ctx: Context) => {
        const context = ctx;
        return context;
      },
      introspection: true // 强制开启 introspection
    });
    

2. 验证子服务端点可用性

直接访问 http://localhost:4001/graphql,在 GraphQL Playground 执行以下 introspection 查询,确认能否正常返回 Schema:

query IntrospectionQuery {
  __schema {
    queryType { name }
    types { name }
  }
}
  • 若查询失败,检查 Product-Service 启动日志,确认 Schema 生成是否存在错误(如 resolver 路径配置错误、类型定义冲突)。

3. 排查认证中间件拦截问题

你的 Product-Service 配置了 authChecker,若该中间件强制要求所有请求携带认证信息,会拦截网关的 introspection 请求:

  • 修改 authChecker,允许 introspection 查询跳过认证:
    export const authChecker: AuthChecker<Context> = ({ context }, roles) => {
      // 识别 introspection 查询并跳过认证
      const isIntrospection = context.req.body?.query?.startsWith('query IntrospectionQuery');
      if (isIntrospection) return true;
      
      // 原有认证逻辑
      return !!context.req.user;
    };
    

4. 检查版本兼容性

不同版本的 Apollo Gateway 与 Apollo Server 可能存在兼容性问题,导致 Schema 请求格式不匹配:

  • 确认 @apollo/gateway、apollo-server、apollo-server-express 为同一大版本系列,避免跨版本调用的格式冲突。

5. 增加请求日志定位细节

在网关的 buildService 中添加日志,查看请求/响应详情:

buildService: ({ name, url }) => {
  return new RemoteGraphQLDataSource({
    url,
    willSendRequest({ request }) {
      console.log(`网关请求 ${url}:`, request);
    },
    didReceiveResponse({ response, request }) {
      console.log(`网关收到响应 ${url}:`, response);
    },
  });
},

通过日志确认网关发送的查询内容,以及子服务返回的具体错误信息,进一步缩小问题范围。

内容的提问来源于stack exchange,提问作者Furkan Gulsen

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.25 23:06:32