功能简介
nginx的fastcgi cache是用来缓存用户请求,当用户下次再进行同样的访问的时候直接将缓存结果返回给用户,避免了nginx再向上游请求结果的过程,使服务性能大幅度提升,如果服务是静态可缓存的话使用这个模块能够明显缩短用户请求时间同时节省服务器资源,大大提升服务的qps。比如我们下边的实例是取自我们线上业务天气服务的fastcgi cache的配置,天气服务之所以能使用这个cache是因为城市数目只有几千个,同时在短暂时间内是不会变化的,也就是是一个可缓存的服务,下边我们会详细介绍对应的配置和服务的压测过程。
配置示例
#cache的目录,采用二级目录hash,16*256目录分级,设置缓存内存空间为10m,官方文档给出的1m能够容纳8000个cache key,对于我们的需求10m是完全够用的,如果需要的cache key比较多增大这个内存量就可以了,最大硬盘占用空间为10g,是所有cache文件所占用硬盘的限制值
#注意,该path设置需要在http块配置中。
fastcgi_cache_path /data/nginx/cache/www.example.com levels=1:2 keys_zone=example:10m max_size=10g;
location ~* \.php$ {
#使用某个cache
fastcgi_cache example;
#当一次请求过来需要写一个cache key的时候,会把这个key锁住,目的是当多个请求同时请求写同一个key的时候只有一个可以去写,其它的等待该key写成功后直接从cache中取,防止了大量请求下穿透cache给后端fastcgi造成过大的压力
fastcgi_cache_lock on
#设置锁过期的时间
fastcgi_cache_lock_timeout 1s;
#设置在什么条件下使用过期的缓存数据,当请求出现错误的时候可以使用过期cache防止出现错误页面
fastcgi_cache_use_stale error timeout updating http_500 http_503;
#设置cache的key
fastcgi_cache_key $host$request_uri;
#设置cache过期时间,可以针对不同的返回码设置不同的过期时间
fastcgi_cache_valid 200 600s;
#设置fastcg的临时目录,cache存放的时候是首先放到这个目录然后移动到cache目录中,官方文档要求这两个目录位于同一个分区以保证性能
fastcgi_temp_path /data/nginx/fastcgi_temp 1 2;
}
fastcgi cache官方文档
上边的配置是取自我们线上服务,我把域名相关信息隐去了,对这个服务进行了压力测试,测试过程及结果如下:
使用压力测试工具为http_load,过程如下:
静态接口压力测试
使用所有城市信息生成对应的测试url,尽量模拟真实请求进行压测。
服务器配置信息:
cpu:8核 Intel(R) Xeon(R) CPU E5-2630 0 @ 2.30GHz
内存:16G
压测过程中我们逐步增大并发数,最终使用两台机器各1000并发进程,100W的请求量去压测我们的单机。
使用不同citycode的url:1000并发,100W的请求量。
http_load执行命令:
./http_load -parallel 1000 -fetches 1000000 -proxy 10.10.10.10:80 urls.txt
http_load返回结果:
1273.67 mean bytes/connection
7583.2 fetches/sec, 9.65848e+06 bytes/sec
msecs/connect: 53.5596 mean, 9006.64 max, 0.157 min
msecs/first-response: 53.024 mean, 3185.14 max, 0.397 min
49 bad byte counts
HTTP response codes:
code 200 – 999951
同时还使用两台机器同时进行压测,每个并发1000个进程,最终得出qps为7000+,同时我们对使用php的动态服务进行了测试,qps大概在300左右,可以看到如果是大量静态的请求使用fastcgi cache提升qps20倍以上。
源码分析
当时我们讨论的时候提到了这个cache的lock具体是怎么实现的,觉得应该去看下源码把这个问题搞清楚
对应源码路径为:nginx/src/http/modules/ngx_http_fastcgi_module.c
暂时没有时间去看,埋个坑回头填上