GraphQL架构
GraphQL架构
Schema设计
GraphQL通过强类型Schema定义API契约,支持查询、变更和订阅。
type Query {
user(id: ID!): User
users(filter: UserFilter, first: Int, after: String): UserConnection!
}
type Mutation {
createUser(input: CreateUserInput!): User!
updateUser(id: ID!, input: UpdateUserInput!): User!
}
type Subscription {
userCreated: User!
}
type User {
id: ID!
name: String!
email: String!
posts: [Post!]!
createdAt: DateTime!
}
input CreateUserInput {
name: String!
email: String!
}
scalar DateTime
N+1问题解决
通过DataLoader批量加载关联数据,解决N+1查询问题。
@Component
public class UserDataLoader {
@Autowired
private UserRepository userRepository;
@BatchLoader
public Map<Long, User> loadUsersByIds(List<Long> ids) {
List<User> users = userRepository.findAllById(ids);
return users.stream()
.collect(Collectors.toMap(User::getId, Function.identity()));
}
}
@Component
public class PostDataFetcher implements DataFetcher<List<Post>> {
@Autowired
private PostRepository postRepository;
@Override
public List<Post> get(DataFetchingEnvironment env) {
User user = env.getSource();
return postRepository.findByUserId(user.getId());
}
}
Apollo Federation
多服务通过Apollo Federation组合成统一的GraphQL网关。
@Configuration
public class FederatedGraphQLConfig {
@Bean
public ApolloFederationSchemaGeneratorwiring schemaGeneratorWiring() {
return ApolloFederationSchemaGeneratorwiring.newWiring()
.type("Post", wiring -> wiring.resolveReference("author",
(env) -> {
Author author = env.getArgument("__typename");
return authorService.findById(author.getId());
}))
.build();
}
}
# Apollo Gateway配置
supergraph:
listen: 0.0.0.0:4000
introspection: true
subgraphs:
users:
routing_url: http://user-service:4001/graphql
schema:
subgraph_url: http://user-service:4001/graphql
posts:
routing_url: http://post-service:4002/graphql
schema:
subgraph_url: http://post-service:4002/graphql
性能优化
通过查询复杂度分析、深度限制和缓存提升GraphQL性能。
@Component
public class QueryComplexityInstrumentation extends SimpleInstrumentation {
private final int maxComplexity;
@Override
public InstrumentationContext<ExecutionResult> beginExecuteOperation(
InstrumentationExecutionParameters params) {
Document document = params.getDocument();
int complexity = calculateComplexity(document);
if (complexity > maxComplexity) {
throw new GraphQLException("Query too complex: " + complexity);
}
return super.beginExecuteOperation(params);
}
}