nginx fastcgi cache 详解

在web项目中,大家都已经非常熟悉其架构流程了。都说Cache是万金油,哪里不舒服抹哪里。这些流程中,几乎每个环节都会进行cache。从浏览器到webserver,到cgi程序,到DB数据库,会进行浏览器cache,数据cache,SQL查询的cache等等。对于fastcgi这里的cache,很少被使用。今年在一个symfony项目中,大量使用了fastcgi cache,大大降低了服务器负载,这里对一些配置进行记录一下。

在http层中做如下配置

fastcgi_temp_path:生成fastcgi_cache临时文件目录

fastcgi_cache_path:fastcgi_cache缓存目录,可以设置目录哈希层级,比如2:2会生成256*256个字目录,keys_zone是这个缓存空间的名字,cache是用多少内存(主要缓存key和文件元信息,不会缓存页面),inactive表示默认失效时间,max_size表示最多用多少硬盘空间,需要注意的是fastcgi_cache缓存是先写在fastcgi_temp_path再移到fastcgi_cache_path,所以这两个目录最好在同一个分区,从0.8.9之后可以在不同的分区,不过还是建议放同一分区。

fastcgi_cache_key:定义fastcgi_cache的key,示例中就以请求的(get|post)+host+URI作为缓存的key,Nginx会取这个key的md5作为缓存文件,如果设置了缓存哈希目录,Nginx会从后往前取相应的位数做为目录。

在server层中的location中做如下配置既可针对特定的路由进行设置

fastcgi_cache:用哪个缓存空间(在http层中我们定义的keys_zone)

fastcgi_cache_valid:定义哪些http头要缓存 示例中200 302 都是1s 缓存 404 500等 0s缓存 其他的状态是1分钟缓存

fastcgi_cache_use_stale:定义哪些情况下用过期缓存

fastcgi_cache_min_uses:URL经过多少次请求将被缓存

配置这些参数时,注意每个参数的作用域,像fastcgi_cache_path参数,只能在http配置项里配置,而fastcgi_cache_min_uses这个参数,可以在http、server、location三个配置项里配置。这样更灵活的会每个域名、每个匹配的location进行选择性cache了。具体的参数作用域,参考FASTCGI模块的官方WIKI。我为了调试方便,添加了一个『X-Cache』的http响应头,$upstream_cache_status 变量表示此请求响应来自cache的状态,$upstream_response_time为过期时间 $upstream_cache_status几种状态分别为:

  • MISS 未命中
  • EXPIRED – expired, request was passed to backend Cache已过期
  • UPDATING – expired, stale response was used due to proxy/fastcgi_cache_use_stale updating Cache已过期,(被其他nginx子进程)更新中
  • STALE – expired, stale response was used due to proxy/fastcgi_cache_use_stale Cache已过期,响应数据不合法,被污染
  • HIT 命中cache

有一些情况会影响到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的值。

很奇怪的一个问题 在symfony框架中测试的时候 如果放在action中测试 缓存一直不生效 查看firebug

fastcgi cache image

我们发现这里有一段cache-control 还有一段过期时间为1981年 如果把代码放在入口文件则缓存正常命中 怀疑是框架初始化的时候干扰了 查了一些资料发现可能是session_start的原因

程序调用session_start时,php的session拓展自己输出的。session.cache_limit参数来决定输出包含哪种Expires的header,默认是nocache,修改php.ini的session.cache_limit参数为“none”即可让session模块不再输出这些http 响应头。或在调用session_start之前,使用session_cache_limiter函数来指定下该参数值。那为什么要在使用session时,发Expires、Cache-Control的http response header呢?我猜测了下,需要session时,基本上是用户跟服务器有交互,那么,既然有交互,就意味着用户的每次交互结果也可能不一样,就不能cache这个请求的结果,给返回给这个用户。同时,每个用户的交互结果都是不一样的,nginx也就不能把包含特殊Cache-Control的个人响应cache给其他人提供了。

非要用session_start 可以如下方式

nginx中还有很多有趣且巧妙的用法 这里就不多讲了 最后贴一份自己的conf的location部分

发表评论

电子邮件地址不会被公开。 必填项已用*标注

您可以使用这些HTML标签和属性: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code class="" title="" data-url=""> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre class="" title="" data-url=""> <span class="" title="" data-url="">