一、关于nginx.conf里的fastcgi_cache配置及如何删除fastcgi缓存
从0.7.48版本开始,Nginx支持类似Squid的缓存功能。这个缓存是把URL及相关组合当做Key(可在nginx配置文件中配置),用Md5算法对Key进行哈希,最后将内容以文本格式得到硬盘上对应的哈希目录路径,从而将缓存内容保存在该目录内。这对一些采用静态页面缓存的新闻网站非常适合,不需要任何代码开发,直接生成缓存。
nginx启用fastcgi缓存最关键的配置1,在http项里加上下面的配置:
fastcgi_cache_path /var/fastcgi_cache_dir levels=1:2 keys_zone=cache_fastcgi:128m inactive=1d max_size=1g;
语法格式:fastcgi_cache_path path [levels=m:n] keys_zone=name:size [inactive=time] [max_size=size]
上述命令指定了fastcgi的配置荐:levels缓存层次,keys_zone 缓存空间名和共享内存大小(热点内容放在内存),inactive 失效时间, 1d = 1天,max_size最大缓存空间(硬盘占用)。这是http模块中必加配置,然后在server模块中结合php的配置里需要添加:
location ~ [^/].php(/|$)
{
try_files $uri =404;
fastcgi_pass unix:/tmp/php-cgi.sock;
fastcgi_index index.php;
include fastcgi.conf;
#fastcgi的缓存配置
expires 20m; #缓存时间20分钟
fastcgi_cache cache_fastcgi; #cache的命令空间,要在nginx配置的keys_zone里
fastcgi_cache_valid 200 301 302 25m; #这些状态码缓存,404之类的不缓存
fastcgi_cache_key $request_method$host$uri$is_args$args; #缓存的key
fastcgi_cache_use_stale error timeout http_500;
add_header X-Cache-Source $upstream_cache_status; #命中缓存时增响应
fastcgi_hide_header X-Powered-By;
fastcgi_connect_timeout 30s;
fastcgi_read_timeout 40s;
fastcgi_send_timeout 30s;
}
加完配置后重启nginx,访问一些URL,就会看到在缓存目录下新生成文件,这些文件格式是:DBase 3 data file。截图如下:
如果要删除缓存直接来这个目录下清空缓存即可,目前虽然知道fastcgi是通过md5加密key来生成的目录名和文件名,但不清楚体的名称和目录名怎么来的。前台访问时可查看头部信息里是否有这项
X-Cache-Source:HIT,如果有就是命中了fastcgi缓存,如果没命中则是X-Cache-Source:MISS
补充:网上有个路径的生成方法,我未检验,不知是否可行,放这里一下:
$cacheFile = $this->_cacheRoot . '/' . substr($md5, -1) . '/' . substr($md5, -3, 2) . '/' . $md5;
二、nginx开启fastcgi缓存时请求php出现页面内容为空问题的原因
某次碰到一个怪问题,请求的接口好好的,但是偶尔出现了请求的内容为空,查看header信息,表示命中了fastcgi缓存:X-Cache-Source:HIT,经过排查发现问题出在fastcgi的缓存key上。
fastcgi_cache_key $host$uri$is_args$args;
如上是服务器里的fastcgi_cache_key的配置,其中的$host$uri$is_args$args参数意义如下:
$host 等于请求头中Host的值。
$uri 等于当前请求中的URI(没有参数,不包括$args)的值。
$is_args 如果设置了$args,那么值为“?”,否则为“”
$args 该变量的值是GET请求在请求行中的参数。
比如访问本站页面:http://kermit.linge/article/99.html?user=kermit 则缓存的KEY为http://kermit.linge/article/99.html?user=kermit,然后所有指向这个URL的请求都会调用这个缓存,看上去没有问题,但是我们忽略了请求不只有GET,还有POST,还有HEAD。而默认fasctcgi是缓存GET和HEAD两种请求。
fastcgi_cache_methods 语法:fastcgi_cache_methods [GET HEAD POST]; 默认值:fastcgi_cache_methods GET HEAD; 使用字段:main,http,location
看配置好像当设置为fastcgi_cache_methods GET;时就只缓存GET,其实不仍,fastcgi无法禁用GET和HEAD请求。即不管你怎么设置它都会缓存GET和HEAD,只有POST是一个可选项,所以当你配置了fastcgi_cache_methods GET后,如果你的页面在fastcgi缓存过期而新缓存未建立的这段时间里有一些HEAD请求(特别是一个服务器监控方面的请求)过来的话(head请求不会返回内容实体信息),就会导致fastcgi生成一些空内容的缓存。可以使用一些在线的head模拟请求或者使用postman测试。而之后再进行GET请求时就会命中这些空内容缓存,显示内容为空。
解决方法是,对缓存根据请求方式进行缓存,修改fastcgi_cache_key的配置值:
fastcgi_cache_key $request_method$host$uri$is_args$args;
然后重启nginx即可(因为key变了,所以不会命中原有的缓存,所以只需重启nginx)。
补充:后来看到有的配置里还会加上:$scheme。
$scheme 表示HTTP scheme(例如HTTP,HTTPS),如果你的页面访问分为https和http,则需要看情况是不是需要加上$scheme当做缓存的key。