graphql请求需精准缓存:仅缓存幂等查询,禁用mutation;用请求体或哈希化参数构造缓存键;按数据敏感度分层设置时效;websocket订阅需单独透传配置。

GraphQL 请求默认不被 Nginx 缓存,尤其是 POST 类型的查询。要真正加速它,核心不是“开启缓存”,而是**精准识别可缓存的请求、构造稳定缓存键、分层控制生命周期,并保障副作用操作不误入缓存**。
只缓存幂等的 GraphQL 查询请求
并非所有 POST /graphql 都适合缓存。关键看语义:
- ✅ 适合缓存:搜索、列表筛选、字典查询(如
query { cities(filter: "sh") })、聚合统计——响应只依赖输入参数,无服务端状态变更 - ❌ 禁止缓存:mutation 操作(如
mutation { createOrder(...) })、含用户会话/权限校验的查询、带随机 token 或时间戳的请求
推荐按路径或请求体特征做区分,例如:
# 仅对明确标记为查询的 POST 启用缓存
if ($request_method = POST) {
set $cache_bypass 1;
# 检查 body 是否含 "mutation" 字符(简单但有效)
if ($request_body ~* "mutation") { set $cache_bypass 0; }
# 或更准:匹配 operationName
if ($request_body ~* "\"operationName\"\s*:\s*\"[^\"]*mutation[^\"]*\"") { set $cache_bypass 0; }
}
proxy_no_cache $cache_bypass;
}
设计能命中缓存的 key
默认 $request_uri 对所有 /graphql 请求都一样,必须引入请求体或关键参数:
- 基础安全写法(小 body、纯文本):
proxy_cache_key "$scheme$request_method$host$request_uri$request_body";
⚠️ 需确保proxy_buffering on;且client_max_body_size足够(如 10M) - 更稳方案(规避大 body 和二进制):
提取标准化参数,例如哈希化 query + variables:proxy_cache_key "$scheme$request_method$host$request_uri$arg_query$arg_variables_hash";
后端可在转发前计算并附加variables_hash参数(如 SHA256)
设置合理且分层的缓存时效
不能统一设 1 小时。应按业务敏感度分级:
- 高频公共数据(城市列表、商品类目):
proxy_cache_valid 200 10m;
加proxy_ignore_headers Cache-Control;强制覆盖后端返回的 no-cache - 中频业务数据(搜索结果、用户公开资料):
proxy_cache_valid 200 30s;
开启proxy_cache_lock on;防穿透,再配proxy_cache_use_stale updating;让旧缓存继续服务 - 低频或强一致性要求(个人订单摘要):
不缓存,或仅缓存 2–5 秒,配合proxy_cache_lock_timeout 3s;严格限流
支持 WebSocket 订阅不中断
GraphQL 订阅(subscription)走 WebSocket,和查询缓存无关,但常共用 /graphql 路径。需单独配置透传:
- 在对应 location 块中启用协议升级:
proxy_http_version 1.1;proxy_set_header Upgrade $http_upgrade;proxy_set_header Connection "upgrade"; - 延长超时防止断连:
proxy_read_timeout 300;proxy_send_timeout 300; - 若订阅有独立路径(如
/graphql/subscriptions),优先按路径分离配置,避免和查询缓存逻辑冲突











