
GraphQL Federation:跨微服务的统一模式
什么是 Federation?
无 Federation:
Client -> 每个服务有自己的 GraphQL 端点
Client -> /api/users/graphql
Client -> /api/orders/graphql
Client -> /api/products/graphql
使用 Federation:
Client -> 单一网关 -> 路由到相应的子图
统一模式:user 有 orders 有 products

子图设置
// users-service/schema.ts
import { buildSubgraphSchema } from '@apollo/subgraph';
import { gql } from 'graphql-tag';
const typeDefs = gql`
extend schema @link(url: "https://specs.apollo.dev/federation/v2.0", import: ["@key", "@shareable"])
type User @key(fields: "id") {
id: ID!
email: String!
name: String!
profile: UserProfile
}
type UserProfile {
bio: String
avatarUrl: String
}
type Query {
me: User
user(id: ID!): User
}
`;
const resolvers = {
Query: {
me: (_, __, { userId }) => userRepo.findById(userId),
user: (_, { id }) => userRepo.findById(id),
},
User: {
// 引用解析器:允许其他子图扩展 User
__resolveReference(reference: { id: string }) {
return userRepo.findById(reference.id);
},
profile: (user) => userProfileRepo.findByUserId(user.id),
},
};
export const schema = buildSubgraphSchema({ typeDefs, resolvers });
// orders-service/schema.ts
const typeDefs = gql`
extend schema @link(url: "https://specs.apollo.dev/federation/v2.0", import: ["@key", "@extends"])
# 从 users-service 扩展 User 类型
type User @key(fields: "id") {
id: ID! @external
orders(first: Int): OrderConnection!
}
type Order @key(fields: "id") {
id: ID!
status: OrderStatus!
total: Float!
createdAt: String!
items: [OrderItem!]!
}
type Query {
order(id: ID!): Order
}
`;
const resolvers = {
User: {
orders: (user, { first = 10 }) => orderRepo.findByUserId(user.id, { limit: first }),
},
Order: {
__resolveReference(ref: { id: string }) {
return orderRepo.findById(ref.id);
},
},
};

Apollo Router(网关)
# router.yaml
supergraph:
listen: 0.0.0.0:4000
subgraphs:
users:
routing_url: http://users-service:4001/graphql
orders:
routing_url: http://orders-service:4002/graphql
products:
routing_url: http://products-service:4003/graphql
# 组合超图模式
rover supergraph compose --config supergraph.yaml > supergraph.graphql
# 启动路由器
./router --config router.yaml --supergraph supergraph.graphql

模式组合
# 生成的统一模式(由 Apollo Router 自动组合)
type User {
id: ID!
email: String!
name: String!
profile: UserProfile # 来自 users-service
orders(first: Int): OrderConnection! # 来自 orders-service
recommendations: [Product!]! # 来自 products-service
}
客户端查询(跨多个服务)
query GetUserDashboard($userId: ID!) {
user(id: $userId) {
name
email
# 由 users-service 解析
profile {
avatarUrl
}
# 由 orders-service 解析
orders(first: 5) {
edges {
node {
id
status
total
}
}
}
}
}
# Apollo Router 自动:
# 1. 从 users-service 获取用户
# 2. 使用 user.id 从 orders-service 获取订单
# 3. 合并并返回组合结果
模式注册表
# 将子图模式发布到 Apollo Studio
rover subgraph publish my-graph@prod \
--name users \
--schema users-service/schema.graphql \
--routing-url https://users-service.internal/graphql
# 在发布前检查破坏性变更
rover subgraph check my-graph@prod \
--name users \
--schema users-service/schema.graphql
Federation 使团队能够独立拥有自己的 GraphQL 模式,同时呈现统一的 API。