这边一直有个php cache的应用,原理是发起一个对自身的请求,保存成静态文件
之前这个应用在apache worker模式跑得很好,换到nginx的fast-cgi 后一直不是很正常
这个问题跟spawn-fcgi的工作原理有关: spawn-fcgi起N个进程,然后FIFO排队处理请求
当有并发>N个PHP CACHE的应用请求过来的时候,php cache的应用会再对自身发起请求,这个请求排在了这些请求的后边,而实际上不会有新的进程来处理这些请求,从而形成死锁,日志中会充斥”upstream timed out” “no live upstreams”
因此,工作模式的排队理论本身决定了这个故障不可避免
解决办法:使用nginx proxy_cache 绕开这个问题,把php cache这个功能交给proxy_cache来完成,nginx的work process遇到阻塞等待的情况,会把这个请求的工作sleep一段时间处理接下来的请求,这个特点明显优于spawn-fcgi的行为
1.建立 /cache/打头的可缓存php location
location ~* ^/cache/(.*\.php)${
…
}
2. 设置相关的proxy_cache:
1) CACHEZONE:
proxy_cache_path /dev/shm/cache/app.gd.sohu.com levels=1:2 keys_zone=default:100m max_size=4g inactive=20m;
2) CACHE目录:
proxy_read_timeout 5s;
proxy_connect_timeout 5s;
proxy_set_header Host $host;
proxy_cache_use_stale updating;
proxy_cache_key “$host$uri$is_args$args”;
proxy_cache default;proxy_ignore_headers “Cache-Control”;
proxy_hide_header “Cache-Control”;proxy_ignore_headers “Expires”;
proxy_hide_header “Expires”;proxy_hide_header “Set-Cookie”;
proxy_ignore_headers “Set-Cookie”;add_header Cache-Control max-age=60;
proxy_cache_valid 200 3m;
proxy_cache_valid any 0m;
proxy_temp_path /dev/shm/cache/tmp;proxy_pass http://serverIP/$1$is_args$args;
3) PURGE设置:
location ~* ^/purge/(.*\.php)$ {
access_log logs/purge_app_access.log sohu;allow 10.10.0.0/16;
deny all;
set $purge_key “$host/$1$is_args$args”;
proxy_cache_purge default $purge_key;}
3.需要注意的地方:
1) 影响动态应用能否cache的有几个header:一般是”X-Accel-Redirect”, “X-Accel-Expires”, “Expires” or “Cache-Control” ,跟某些文档提到的cookie是没有关系的,我这里根据自己的应用ignore了 “Expires” 和”Cache-Control” 的header
2) 需要注意,php使用cookie(session也是cookie header实现的一种)来识别用户,如果是私密应用,需要把cookie加入cachekey里边,开放式应用则不必如此
3)设置完毕后可以在访问路径的前边加上/cache/实现php内容的缓存,再加上/purge/就能清除其缓存
4) 需要特别说明,我这边的版本是0.7系列,从测试看1.x系列是会forward cookie的,所以需要抹掉:
proxy_hide_header Set-Cookie;
proxy_ignore_headers Set-Cookie;
2022.07补充
By default, NGINX respects other directives in the Cache-Control
header: it does not cache responses when the header includes the Private
, No-Cache
, or No-Store
directive. It also doesn’t cache responses with the Set-Cookie
header. Further, it only caches responses to GET
and HEAD
requests. You can override these defaults as described in the answers below.