- 流程:
用户第一次请求,会把返回的文件同时缓存起来,如果再有请求,命中缓存直接从cache返回数据,省去了fastcgi和php通信处理过程
- 原理:
NGINX作为Cache服务器时将资源内容以文件形式进行缓存,缓存元信息存储于共享内存中,组织成一棵红黑树。红黑树中的每个节点代表一个Cache元信息。NGINX将Cache Key(URL 以及相关组合)的HASH值作为红黑树节点的KEY。内容缓存文件以该HASH值作为文件名存储在磁盘上。
缓存过程: 两个Nginx 进程参与缓存,cache loader 和 cache manager。cache manager 定期激活检查缓存文件存在器的状态。特别地,当文件存储器的大小超过 max_size 参数的值时,把最近最少使用到的数据删除。cache loader 只激活一次,在Nginx启动之后。它加载先前缓存的数据的元信息到共享内存区。一次性在头一分钟内加载所有的缓存可能会消耗大量的资源和减慢 Nginx 的性能。
- 配置:
-
nginx 配置示范1234567891011121314151617181920212223242526272829303132
fastcgi_cache_path /data/service_data/xinche-operate/cache levels=1:2 keys_zone=DOMAIN_CACHE:100m max_size=300m inactive=1h;
add_header X-Cache
"$upstream_cache_status"
;
server {
…
location ~* .*.php?$
{
//接口层面
set
$cache
1;
if
(
$http_fpmcache
= 1 ){
set
$cache
0;
//如何header 传fpmcache 1 代表使用缓存
}
fastcgi_cache_key
$scheme
$host
$request_uri
$request_method
;
//一定要加上$request_method作为cache key,否则如果HEAD类型的先请求会导致后面的GET请求返回为空,
fastcgi_cache DOMAIN_CACHE;
fastcgi_cache_valid 200 302 301 10m;
fastcgi_cache_use_stale updating error timeout invalid_header http_500 http_503 http_404;
fastcgi_ignore_headers Cache-Control Expires Set-Cookie;
fastcgi_cache_bypass
$cookie_nocache
;
fastcgi_no_cache
$cache
;
add_header X-Cache
$cache
;
fastcgi_pass 127.0.0.1:9001;
fastcgi_index index.php;
fastcgi_split_path_info ^(.+.php)(.*)$;
fastcgi_param PATH_INFO
$fastcgi_path_info
;
fastcgi_param SCRIPT_FILENAME
$document_root
$fastcgi_script_name
;
include
fastcgi_params;
set
$cors
""
;
if
(
$http_origin
~*
'(localhost|10.216.90.170|crm.xinche.guazi-corp.com|xinche-saler.guazi.com|xinche-order.guazi.com|xinche-operate.guazi.com)'
) {
set
$cors
"true"
;
}
}
- 关注状态点:
$upstream_cache_status 变量表示此请求响应来自cache的状态,几种状态分别为:
- MISS – The response was not found in the cache and so was fetched from an origin server. The response might then have been cached.
- BYPASS – The response was fetched from the origin server instead of served from the cache because the request matched a proxy_cache_bypass directive (see Can I Punch a Hole Through My Cache? below.) The response might then have been cached.
- EXPIRED – The entry in the cache has expired. The response contains fresh content from the origin server.
- STALE – The content is stale because the origin server is not responding correctly, and proxy_cache_use_stale was configured.
- UPDATING – The content is stale because the entry is currently being updated in response to a previous request, and proxy_cache_use_stale updating is configured.
- REVALIDATED – The proxy_cache_revalidate directive was enabled and NGINX verified that the current cached content was still valid (If-Modified-Since or If-None-Match).
- HIT – The response contains valid, fresh content direct from the cach
有一些情况会影响到cache的命中 这里需要特别注意
- Nginx fastcgi_cache在缓存后端fastcgi响应时,当响应里包含“set-cookie”时,不缓存;
- 当响应头包含Expires时,如果过期时间大于当前服务器时间,则nginx_cache会缓存该响应,否则,则不缓存;
- 当响应头包含Cache-Control时,如果Cache-Control参数值为no-cache、no-store、private中任意一个时,则不缓存,如果Cache-Control参数值为max-age时,会被缓存,且nginx设置的cache的过期时间,就是系统当前时间 + mag-age的值
解决: - 加上fastcgi_ignore_headers Cache-Control Expires Set-Cookie;可以解决这个问题
- 性能对比:
四核逻辑cpu
4G 内存
使用Jmeter 压测
10.16.208.86 (g1-nc-test-v02)
-
g1-nc-test-v02 线程/sec tps 接口平均响应 cpu 100 270/sec 253ms 60%-70% 150 240/sec 494ms 70%-84% 200 281/sec 561ms 84%左右 300 280/sec 901ms 84%左右 500 264/sec 1481ms 84%左右
使用了fastcgi_cache
四核逻辑cpu
4G 内存
使用Jmeter 压测
10.16.208.87 (g1-nc-test-v01)
-
g1-nc-test-v01 线程/sec tps 接口平均响应 cpu 100 832/sec 27ms 5%下 150 1067/sec 39ms 5%下 200 1294/sec 64ms 5%下 300 1107/sec 153ms 5%下 500 955/sec 284ms 5%下
以上对比结果: 使用了fastcgi_cache 对QPS 有大概3-5倍的提升速度。(本地单机实测,使用是未使用的10倍左右)。
-
缓存命中率
遗憾没有相关命令去查看或者统计缓存命中率,只能通过把$upstream_cache_status 打到日志上统计了。目前测试命中率大概处于88%-98%之间
1234567891011121314//
类似shell脚步统计
if
[
"$1"
!=
''
];
then
if
[ -e
"$1"
];
then
HIT=`
cat
$1 |
grep
HIT |
wc
-l`
ALL=`
cat
$1 |
wc
-l`
HIT_RATE=`
echo
"scale=2;($HIT/$ALL)*100"
|
bc
`
echo
"HIT_rate = $HIT_RATE"
else
echo
"$1 xxxxxx"
fi
else
xxxxx
fi
- 清除缓存
NGINX只在商业版中支持proxy_cache_purge指令清除缓存,开源的ngx_cache_purge模块只支持单一key的缓存清除。(未测)
- 缺点:
Fastcgi_cache不会去检测php是否更新,所以如果有内容更新后页面不会更新
FastCGI Cache不支持分布式缓存,当服务器很多的时候,冗余的浪费将非常严重,此外还有数据一致性问题,所以它只是一个粗线条的解决方案。
后续分析下ngx_srcache | lua-resty-cache 这两个细粒度相对高的组件。
参考:
https://huoding.com/2014/01/13/321
https://www.ruby-forum.com/topic/3302927
http://jianjye.com/set-nginx-cache-laravel-php-app-5-mins/