GraphQL 是什么
GraphQL 是一种由客户端声明所需字段的查询语言:服务端定义强类型模式(Schema),客户端提交查询只取需要的字段,单端点即可完成过去需要多个接口拼装的数据获取。它的代价集中在服务端治理:查询结构由客户端决定,嵌套与别名的组合可能放大成昂贵扫描,因此必须有深度限制、复杂度计分与超时控制。此外它通常用 POST 提交单端点,与基于 URL 的 HTTP 缓存机制不兼容,需要考虑持久化查询等替代方案。
基本信息
| 端点 | 通常为单一端点,查询结构由客户端提交 |
|---|---|
| 模式 | 强类型 Schema,可自省,可作为契约与文档 |
| 缓存 | 以 POST 单端点为主,HTTP 缓存效果有限,需应用层或持久化查询 |
| 治理 | 深度限制、复杂度计分、超时与结果条数上限 |
| N+1 风险 | 解析器逐字段取数,需要批量加载机制配合 |
典型使用场景
- 多端共用接口:移动端与网页端按各自需要取字段,减少接口定制
- 页面聚合:一次查询拿到页面所需的多个实体,替代多次串行请求
- 快速迭代的前端:新增字段无需新增接口,前端可自主选择数据
- 内部工具与后台:字段灵活可选的场景,减少后端定制开发
- 模式驱动开发:以 Schema 作为契约,配合代码生成减少手写类型
- 跨服务聚合:网关层把多个下游数据源组装成一个查询入口
查询示例
查询示例
query OrderWithCustomer {
order(id: "1001") { # 按需取数:只要页面用到的字段
id
total
status
customer { name } # 关联对象只取姓名,避免过度获取
}
}
# 服务端必须在入口设置上限,否则深度与别名叠加会放大成昂贵查询
# 常见做法:限制嵌套层数(如 10 层)
# 按字段权重计分,超过阈值直接拒绝
# 强制游标分页,禁止无界列表服务端治理清单
| 项 | 做法 | 说明 |
|---|---|---|
| 深度限制 | 限制嵌套层数(如 10 层) | 防止别名递归放大 |
| 复杂度计分 | 按字段权重计分,超阈值拒绝 | 比单纯限深度更贴近真实成本 |
| 持久化查询 | 常用查询白名单化 | 收窄任意查询面,同时改善缓存 |
| 分页 | 强制游标分页 | 禁止返回无界列表 |
| 批量加载 | 用批量加载机制解决 N+1 | 否则一次查询会打爆数据库 |
必须为查询设置深度、复杂度与超时上限:嵌套与别名叠加可能把一个看似简单的查询放大成全表扫描,这类请求在日志里往往只表现为一条慢查询。
沿用基于 URL 的 HTTP 缓存方案时基本失效:GraphQL 以 POST 单端点为主,应改用持久化查询、服务端结果缓存或字段级缓存策略。