Nginx:根据HTTP方法启用/禁用缓存

7

我在serverfault上提出了这个问题,但是没有人回答。希望stackoverflow的人更了解Nginx :)

我想要将所有对/api的[GET]请求都处理为缓存,并将所有其他请求处理为最后一个位置块中的内容(不使用缓存)。所有使用PUT、POST、DELETE方法的/api请求也不能使用缓存。

我看到了类似的问题here,但仍然不知道如何在我的情况下使用它。

先谢谢了。

我的配置:

location / {
    root /var/www/project/web;
    # try to serve file directly, fallback to app.php
    try_files $uri /app.php$is_args$args;
}


location ~ ^/api {
    root /var/www/project/web/app.php;
    fastcgi_send_timeout 600s;
    fastcgi_read_timeout 600s;
    fastcgi_pass unix:/var/run/php5-fpm.sock;
    fastcgi_split_path_info ^(.+\.php)(/?.*)$;
    include fastcgi_params;
    fastcgi_cache fcgi;
    fastcgi_cache_valid 200 5m;
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    fastcgi_param HTTPS off;

}

location ~ ^/(app|app_dev|config)\.php(/|$) {
    root /var/www/project/web;
    fastcgi_send_timeout 600s;
    fastcgi_read_timeout 600s;
    fastcgi_pass unix:/var/run/php5-fpm.sock;
    fastcgi_split_path_info ^(.+\.php)(/?.*)$;
    include fastcgi_params;
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    fastcgi_param HTTPS off;
}
1个回答

9
很简单,感谢上帝。Nginx的模块(代理,fastcgi,uwsgi等)都有能力通知请求不使用缓存。
location ~ ^/api {
    root /var/www/project/web/app.php;
    fastcgi_send_timeout 600s;
    fastcgi_read_timeout 600s;
    fastcgi_pass unix:/var/run/php5-fpm.sock;
    fastcgi_split_path_info ^(.+\.php)(/?.*)$;
    include fastcgi_params;

    # Don't cache anything by default
    set $no_cache 1;

    # Cache GET requests
    if ($request_method = GET)
    {
        set $no_cache 0;
    }

    fastcgi_cache_bypass $no_cache;
    fastcgi_no_cache $no_cache;

    fastcgi_cache fcgi;
    fastcgi_cache_valid 200 5m;
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    fastcgi_param HTTPS off;
}

根据Richard Smith的建议,使用maps指令的更优雅的解决方案如下:
map $request_method $api_cache_bypass {
    default       1;
    GET           0;
}

location ~ ^/api {
    root /var/www/project/web/app.php;
    fastcgi_send_timeout 600s;
    fastcgi_read_timeout 600s;
    fastcgi_pass unix:/var/run/php5-fpm.sock;
    fastcgi_split_path_info ^(.+\.php)(/?.*)$;
    include fastcgi_params;

    fastcgi_cache_bypass $api_cache_bypass;
    fastcgi_no_cache $api_cache_bypass;

    fastcgi_cache fcgi;
    fastcgi_cache_valid 200 5m;
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    fastcgi_param HTTPS off;
}

对于这个位置的补充,实际上是告诉Nginx根据动词使用或忽略缓存。它将$no_cache设置为1,这将绕过所有请求的缓存,除非方法是GET,此时它设置为0,指示它使用缓存(如果可用)。


1
你考虑过使用map而不是set/if/set方法吗? - Richard Smith
If语句也可能会产生意外的副作用,但就性能而言,我真的不知道。但是使用map解决方案看起来更加优雅 :-) - Richard Smith
是的,这很公平。我唯一担心的是它只在http上下文中可用,这可能会有点混淆,如果不同位置有不同的缓存要求,就必须重复使用变量名(尽管这可能性很小)。我也会加入一个地图选项,因为我喜欢它。 - justcompile
我只是明确地定义了这些动词,以便如果他们需要/想要更改它们,那么更改就会更容易...但看起来你更注重优雅 ;) - justcompile
非常感谢大家的回答! :) - zIs
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接