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

如何通过单一URL访问多Spring Boot GraphQL微服务?网关选型与实现

问题解答

一、Apollo Gateway 是否适用于你的场景?

完全合适。Apollo Gateway是GraphQL联邦(Federation)的官方实现,专门用于整合多个独立的GraphQL服务,对外暴露统一的API入口。它能自动合并各子服务的Schema,根据查询字段自动路由到对应的后端服务,正好匹配你将userlist查询转发到/graphql1、产品相关查询转发到/graphql2的需求。

需要注意的是:Apollo Gateway本身基于Node.js开发,如果你希望网关完全落在Java技术栈里,可以考虑Java生态的替代方案(比如后文提到的Spring GraphQL或Netflix DGS Federation);但如果不介意引入Node.js组件,Apollo Gateway是非常成熟的选择。

二、实现统一GraphQL网关的具体方案

方案1:使用Apollo Gateway(跨技术栈)

  1. 子服务配置GraphQL联邦支持
    以Spring GraphQL为例,给每个子服务添加联邦依赖:

    <!-- pom.xml 依赖 -->
    <dependency>
        <groupId>com.apollographql.federation</groupId>
        <artifactId>federation-spring-boot-starter</artifactId>
        <version>2.0.0</version>
    </dependency>
    

    在User服务的Schema中标记联邦类型:

    extend type Query {
        userlist: [User]
    }
    
    type User @key(fields: "id") {
        id: ID!
        name: String!
    }
    

    Product服务同理,定义自己的Query和联邦类型。

  2. 搭建Apollo Gateway
    创建Node.js项目,安装依赖:

    npm install @apollo/gateway apollo-server
    

    编写网关配置,指定子服务地址:

    const { ApolloServer } = require('apollo-server');
    const { ApolloGateway } = require('@apollo/gateway');
    
    const gateway = new ApolloGateway({
        serviceList: [
            { name: 'user-service', url: 'http://localhost:8080/graphql1' },
            { name: 'product-service', url: 'http://localhost:8081/graphql2' }
        ]
    });
    
    const server = new ApolloServer({ gateway });
    
    server.listen(4000).then(({ url }) => {
        console.log(`Gateway ready at ${url}`);
    });
    

    启动网关后,访问http://localhost:4000/graphql即可发起统一查询,网关会自动路由到对应子服务。

方案2:Java技术栈内实现(Spring GraphQL + Gateway)

如果希望网关完全基于Java,推荐Spring生态组合方案:

  1. 子服务保持原有配置
    确保User和Product服务的Schema清晰划分各自的查询与类型。

  2. 搭建Spring Gateway + Spring GraphQL网关服务
    创建新Spring Boot项目,添加依赖:

    <!-- pom.xml 依赖 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-gateway</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.graphql</groupId>
        <artifactId>spring-boot-starter-graphql</artifactId>
    </dependency>
    

    自定义Schema合并与路由逻辑:

    @Configuration
    public class GraphQLGatewayConfig {
        @Bean
        public GraphQlSourceBuilderCustomizer sourceBuilderCustomizer(RestTemplate restTemplate) {
            return builder -> builder.schemaFactory((resources, environment) -> {
                // 拉取子服务Schema并合并
                String userSchema = restTemplate.getForObject("http://localhost:8080/graphql1/schema", String.class);
                String productSchema = restTemplate.getForObject("http://localhost:8081/graphql2/schema", String.class);
                return SchemaParser.parse(userSchema + "\n" + productSchema);
            });
        }
    
        @Bean
        public RuntimeWiringConfigurer runtimeWiringConfigurer(RestTemplate restTemplate) {
            return wiringBuilder -> wiringBuilder
                .type("Query", typeWiring -> typeWiring
                    .dataFetcher("userlist", env -> {
                        // 转发请求到User服务
                        return restTemplate.postForObject(
                            "http://localhost:8080/graphql1",
                            Map.of("query", "{ userlist { id name } }"),
                            Map.class
                        ).get("data").get("userlist");
                    })
                    .dataFetcher("productlist", env -> {
                        // 转发请求到Product服务
                        return restTemplate.postForObject(
                            "http://localhost:8081/graphql2",
                            Map.of("query", "{ productlist { id name } }"),
                            Map.class
                        ).get("data").get("productlist");
                    })
                );
        }
    }
    

    配置Spring Gateway路径映射:

    spring:
      cloud:
        gateway:
          routes:
            - id: graphql-gateway
              uri: http://localhost:8082 # 网关自身地址
              predicates:
                - Path=/graphql
    

    启动网关后,访问http://localhost:8082/graphql即可统一访问两个子服务的API。

方案3:使用Netflix DGS Federation(全Java栈)

Netflix DGS是Spring生态的GraphQL框架,原生支持联邦特性:

  1. 子服务添加DGS Federation依赖,在Schema中标记联邦类型;
  2. 创建DGS Gateway服务,配置子服务地址,网关会自动合并Schema并完成请求路由。

三、关键注意事项

  • Schema一致性:避免子服务出现同名类型但字段不一致的情况,联邦模式下可通过@extends和@key实现类型扩展;
  • 性能优化:网关层可添加请求缓存、批量请求合并等逻辑,减少子服务重复调用;
  • 监控与日志:在网关层统一收集请求日志和监控数据,便于问题排查。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 16:07:05