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

将POST请求体作为NGINX缓存键的配置未按预期生效

NGINX作为GraphQL反向代理时POST请求缓存失效问题

我尝试将NGINX用作GraphQL服务器的反向代理并启用NGINX缓存功能。计划对POST API请求的响应进行缓存,同时将请求体和API URL纳入缓存键的组成部分,但配置未按预期工作:即使修改API请求的payload,仍会收到首次缓存的相同响应,不确定配置中存在什么问题。

现有配置

worker_processes  1;

error_log  C:/Workspace/error.log;

events {
    worker_connections  1024;
}

http {
    # 定义缓存路径及设置
    proxy_cache_path "C:/Users/username/Documents/cache" levels=1:2 keys_zone=my_cache:100m max_size=200m inactive=5m;

    limit_req_zone $binary_remote_addr zone=mylimit:10m rate=10r/m;

    include       mime.types;
    default_type  application/octet-stream;

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  logs/access.log  main;

    sendfile        on;
    keepalive_timeout  65;
    
    server {
        listen       8081;
        server_name  localhost;
        
        location /api {
            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection "upgrade";
            proxy_set_header Host localhost;
            proxy_pass http://localhost:8080;
            # 启用请求体缓冲并设置缓冲区大小
            proxy_buffers 8 32M;
            proxy_buffer_size 30M;
            client_body_buffer_size 10M;  # 根据需求调整大小        
#           proxy_buffering on;           # 启用代理缓冲
          #  proxy_ignore_headers "Set-Cookie";
          #  proxy_hide_header "Set-Cookie";
            proxy_hide_header Cache-Control;
            proxy_cache_methods GET POST;
            # 基于请求协议、方法和URI定义缓存键
            set $cache_key "$scheme$request_method$request_uri|$request_body";

            # 根据x-api-cache头设置是否缓存的标志
            set $cache_condition 0;
            if ($http_x_api_cache != "true") {
                set $cache_condition 1;
            }

            # 仅当条件为true时启用缓存
            proxy_cache my_cache;
            proxy_cache_key $cache_key;
            proxy_cache_bypass $cache_condition;
            proxy_no_cache $cache_condition;
            proxy_cache_valid 200 5m;

            # 添加X-Cache-Status头显示缓存状态
            add_header X-Cache-Status $upstream_cache_status;
        }
    }
}

问题分析与修复方案

1. 请求体未被正确读取

NGINX默认在处理set指令时,可能还未完整读取请求体,导致$request_body变量为空或不完整,最终不同payload使用了相同的缓存键,出现缓存命中错误。

修复:取消注释proxy_buffering on;,开启代理缓冲功能。该配置会让NGINX先将请求体完整缓冲到内存或磁盘,确保$request_body能正确获取到完整的请求内容。

2. 缓存键优化(可选但推荐)

直接使用$request_body作为缓存键的一部分,可能因请求体的格式差异(如空格、换行)导致不必要的缓存键差异,同时过长的请求体也会导致缓存键体积过大。建议使用NGINX 1.17.9及以上版本支持的$request_body_hash变量,对请求体进行哈希处理:

set $cache_key "$scheme$request_method$request_uri|$request_body_hash";

这样相同内容的请求体(无论格式)会生成相同哈希,不同内容则生成不同哈希,既保证缓存区分度,又优化缓存键长度。

3. 缓存条件逻辑验证

当前配置的缓存条件逻辑是:仅当请求头x-api-cache=true时才会使用缓存并存储响应。如果你的需求是默认缓存POST请求,仅在特定头下跳过缓存,需要调整逻辑:

set $cache_condition 0;
if ($http_x_api_cache = "false") {
    set $cache_condition 1;
}

这样只有当x-api-cache=false时,才会跳过缓存并不存储响应,其余情况正常缓存。

4. 缓存目录权限检查

Windows环境下需确保NGINX进程对C:/Users/username/Documents/cache目录有读写权限,否则缓存无法正常写入,可能导致始终返回旧缓存或无法缓存。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 19:41:05