nginx缓存cache的几种方式
1、nginx的proxy_cache功能从nginx-0.7.44版开始,nginx支持了类似squid较为正规的cache功能。这个缓存是把链接用md5编码hash后保存,所以它可以支持任意链接,同时也支持404/301/302这样的非200状态。配置:首先配置一个cache空间(在http之下):proxy_cache_path /xok/to/cache levels=1:2 keys_z inactive=5m max_size=1g clean_time=1m;proxy_temp_path参数路径也需要跟上面的proxy_cache_path在一个分区上,否则会报错。注意这个配置是在server标签外,levels指定该缓存空间有两层hash目录,第一层目录是1个字母,第二层为2个字母,保存的文件名就会类似 /xok/to/cache/e/4a/0f1019b0db2f97d17c2238c0271a74ae;keys_zone为这个空间起个名字,50m指共享内存空间大小为50MB,即内存缓存空间(活跃);inactive的5m指缓存默认时长5分钟;max_size的1g是指总的缓存空间大小为1g,磁盘缓存空间,当缓存总大小超过该值,将执行lru策略;clean_time指定一分钟清理一次缓存。 location / { proxy_pass http://xok.la/; proxy_cache xok1;#使用xok1这个keys_zone proxy_cache_valid 200 302 1h;#200和302状态码保存1小时 proxy_cache_valid 301 1d;#301状态码保存一天 proxy_cache_valid any 1m;#其它的保存一分钟 }这里给出一个常用的例子:
location ~ ^/(xx|yy)\.action{
proxy_set_header Accept-Encoding "";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
add_header X-Cache $upstream_cache_status; //看解释1
proxy_cache dream_cache;
proxy_cache_key $host$uri$is_args$arg_pageNo$arg_subjectId;//看解释2
proxy_cache_methods GET POST;
proxy_cache_valid 200 301 302 5s;
proxy_cache_use_stale error timeout updating http_404 http_500 http_502 http_503;//看解释3
proxy_cache_lock on;//看解释4
proxy_cache_lock_timeout 5s;
proxy_pass http://localhost;
}
解释1:
add_header X-Cache $upstream_cache_status;是让我们可以方便地通过reponse的头部观察缓存命中状态。
nginx提供了$upstream_cache_status这个变量来显示缓存的状态,我们可以在配置中添加一个http头来显示这一状态,达到类似squid的效果。
$upstream_cache_status包含以下几种状态:
·MISS 未命中,请求被传送到后端
·HIT 缓存命中
·EXPIRED 缓存已经过期请求被传送到后端
·UPDATING 正在更新缓存,将使用旧的应答
·STALE 后端将得到过期的应答
解释2:
proxy_cache_key $host$uri$is_args$arg_pageNo$arg_subjectId;指定了缓存的key,一般是url。这里注意两个变量:
(1)$is_args'?'问号
(2)$args;表示问号后面的所有参数
这里的例子的写法我认为更需要懂得,这是指定部分参数的写法,pageNo、和subjectId两个参数,而忽略其他的参数,比如遇到有加时间戳的时候,可以忽略掉时间戳,否则缓存永远也不会命中的。
解释3:
proxy_cache_use_stale error timeout updating http_404 http_500 http_502 http_503;
proxy_cache_use_stale 指定后端服务器出现什么状况时,nginx可以使用的过期缓存。
比如制定了updating,它将保证只有一个线程去更新缓存,并且在这个线程更新缓存的过程中其他的线程只会响应当前缓存中的过期版本。
解释4:
proxy_cache_lock on;
#定义相同的请求,同时只允许一个请求发往后端,并根据proxy_cache_key往内存中写新#条目,直接proxy_cache_lock_time超时被释放proxy_cache_lock on |off #default offproxy_cache_lock_timeout time #default 5s接下来附上一些介绍:
1 proxy_cache
语法:proxy_cache zone_name;
默认值:None
使用字段:http, server, location
设置一个缓存区域的名称,一个相同的区域可以在不同的地方使用。
在0.7.48后,缓存遵循后端的”Expires”, “Cache-Control: no-cache”, “Cache-Control: max-age=XXX”以及其他等。然而,目前nginx会忽略一些缓存控制指令,如:”private”和”no-store”,同样,nginx在缓存过程中不会处理”Vary”头,为了确保一些私有数据不被所有的用户看到,后端必须设置 “no-cache”或者”max-age=0″头,或者proxy_cache_key包含用户指定的数据如$http_cookie_xxx,在proxy_cache_key中使用一部分cookie的值可以防止缓存私有数据,所以可以分别指定location以便分开私有数据和公有数据。
缓存指令依赖代理缓冲区(buffers),如果proxy_buffers设置为off,缓存不会生效。
2 proxy_cache_key
语法:proxy_cache_key line;
默认值:$scheme$proxy_host$request_uri;
使用字段:http, server, location
指令指定了包含在缓存中的缓存关键字。
proxy_cache_key
"$host$request_uri$cookie_user"; |
proxy_cache_key
"$scheme$host$request_uri"; |
3 proxy_cache_path
语法:proxy_cache_path path [levels=number] keys_z [inactive=time] [max_size=size];默认值:None使用字段:http指令指定缓存的路径和一些其他参数,缓存的数据存储在文件中。缓存的文件名和key为代理URL的MD5 码。levels参数指定缓存的子目录数,例如:proxy_cache_path
/data/nginx/cache levels=1:2 keys_z/td> |
文件名类似于:/data/nginx/cache/c/29/b7f54b2df7773722d382f4809d65029c所有活动的key和元数据存储在共享的内存区域中,这个区域用keys_zone参数指定,如果在inactive参数指定的时间内缓存的数据没有被请求则被删除,默认inactive为10分钟。cache manager进程控制磁盘的缓存大小,在max_size参数中定义,超过其大小后最少使用数据将被删除。区域的大小按照缓存页面数的比例进行设置,一个页面(文件)的元数据大小按照操作系统来定,FreeBSD/i386下为64字节,FreeBSD/amd64下为128字节,当区域满了以后key将按照LRU(最近最少使用算法)进行处理。proxy_cache_path和proxy_temp_path应该使用在相同的文件系统上。
4 proxy_cache_methods
语法:proxy_cache_methods [GET HEAD POST];
默认值:proxy_cache_methods GET HEAD;
使用字段:http, server, location
GET/HEAD用来装饰语句,即你无法禁用GET/HEAD即使你只使用下列语句设置:
proxy_cache_methods
POST; |
5 proxy_cache_min_uses
语法:proxy_cache_min_uses the_number;默认值:proxy_cache_min_uses 1;使用字段:http, server, location多少次的查询后应答将被缓存,默认1。
6 proxy_cache_valid
语法:proxy_cache_valid reply_code [reply_code ...] time;
默认值:None
使用字段:http, server, location
为不同的应答设置不同的缓存时间,例如: proxy_cache_valid 200 302 10m; proxy_cache_valid 404 1m; proxy_cache_valid 5m; proxy_cache_valid 200 302 10m; proxy_cache_valid 301 1h; proxy_cache_valid any 1m;
7 proxy_cache_use_stale
为了防止缓存失效(在多个线程同时更新本地缓存时),你可以指定’updating’参数,它将保证只有一个线程去更新缓存,并且在这个线程更新缓存的过程中其他的线程只会响应当前缓存中的过期版本。
代码及configure配置:
在ngx_http_proxy_module.c里面定义了每个指令的钩子(即callback),它们在读取配置文件时会被调用。在configure的时候只需要把“HTTP_CACHE”设置为YES(可以找到auto/options里面HTTP_CACHE那行)。“proxy_cache_purge”指令需要下载nginx
add-ons里面的“Cache Purge”模块,并在configure的时候用"--add-module="来加载代码。
以下附件一些其他nginx缓存内容,但是现在很少使用了,有兴趣可以了解下:
二、传统缓存之一(404)这个办法是把nginx的404错误定向到后端,然后用proxy_store把后端返回的页面保存。 location / { root /home/html/;#主目录 expires 1d;#网页的过期时间 error_page 404 =200 /fetch$request_uri;#404定向到/fetch目录下 } location /fetch/ {#404定向到这里 internal;#指明这个目录不能在外部直接访问到 expires 1d;#网页的过期时间 alias /home/html/;#虚拟目录文件系统地址要和locaion /一致,proxy_store会将文件保存到这目录下 proxy_pass http://xok.la/;#后端upstream地址,/fetch同时是一个代理 proxy_set_header Accept-Encoding '';#让后端不要返回压缩(gzip或deflate)的内容,保存压缩后的内容会引发乱子。 proxy_store on;#指定nginx将代理返回的文件保存 proxy_temp_path /home/tmp;#临时目录,这个目录要和/home/html在同一个硬盘分区内 }使用的时候还有要注意是nginx要有权限往/home/tmp和/home/html下有写入文件的权限,在linux下nginx一般会配置成 nobody用户运行,这样这两个目录就要chown nobody,设成nobody用户专用,当然也可以chmod 777,不过所有有经验的系统管理员都会建议不要随便使用777。三、传统缓存之二(!-e)原理和404跳转基本一致,但更简洁一些: location / { root /home/html/; proxy_store on; proxy_set_header Accept-Encoding ''; proxy_temp_path /home/tmp; if ( !-f $request_filename ) { proxy_pass http://xok.la/; } }可以看到这个配置比404节约了不少代码,它是用!-f来判断请求的文件在文件系统上存不存在,不存在就proxy_pass到后端,返回同样是用proxy_store保存。两种传统缓存都有着基本一样的优点和缺点:缺点1:不支持带参数的动态链接,比如read.php?id=1,因为nginx只保存文件名,所以这个链接只在文件系统下保存为read.php,这样用户访问read.php?id=2时会返回不正确的结果。同时不支持http://xok.la/这种形式的首页和二级目录http:
//xok.la/download/,因为nginx非常老实,会将这样的请求照链接写入文件系统,而这个链接显然是一个目录,所以保存失败。这些情况都需要写rewrite才能正确保存。缺点2:nginx内部没有缓存过期和清理的任何机制,这些缓存的文件会永久性地保存在机器上,如果要缓存的东西非常多,那就会撑暴整个硬盘空间。为此可以使用一个shell脚本定期清理,同时可以撰写php等动态程序来做实时更新。缺点3:只能缓存200状态码,因此后端返回301/302/404等状态码都不会缓存,假如恰好有一个访问量很大的伪静态链接被删除,那就会不停穿透导致后端承载不小压力。缺点4:nginx不会自动选择内存或硬盘作为存储介质,一切由配置决定,当然在当前的操作系统里都会有操作系统级的文件缓存机制,所以存在硬盘上也不需要过分担心大并发读取造成的io性能问题。nginx 传统缓存的缺点也是它和squid等缓存软件的不同之特色,所以也可看作其优点。在生产应用中它常常用作和squid的搭档,squid 对于带?的链接往往无法阻挡,而nginx能将其访问拦住,例如:http://xok.la/?和http://xok.la/在squid上会被当做两个链接,所以会造成两次穿透;而nginx只会保存一次,无论链接变成http://xok.la/?1还是http://xok.la/?123,均不能透过nginx缓存,从而有效地保护了后端主机。nginx会非常老实地将链接形式保存到文件系统中,这样对于一个链接,可以很方便地查阅它在缓存机器上的缓存状态和内容,也可以很方便地和别的文件管理器如rsync等配合使用,它完完全全就是一个文件系统结构。这两种传统缓存都可以在linux下将文件保存到/dev/shm里,一般我也是这么做的,这样可以利用系统内存来做缓存,利用内存的话,清理过期内容速度就会快得多。使用/dev/shm/时除了要把tmp目录也指向到/dev/shm这个分区外,如果有大量小文件和目录,还要修改一下这个内存分区的
inode数量和最大容量: mount -o size=2500M -o nr_inodes=480000 -o noatime,nodiratime -o remount /dev/shm上面的命令在一台有3G内存的机器上使用,因为/dev/shm默认最大内存是系统内存的一半就是1500M,这条命令将其调大成2500M,同时 shm系统inode数量默认情况下可能是不够用的,但有趣的是它可以随意调节,这里调节为480000保守了点,但也基本够用了。四、基于memcached的缓存nginx对memcached有所支持,但是功能并不是特别之强,性能上还是非常之优秀。 location /mem/ { if ( $uri ~ "^/mem/([0-9A-Za-z_]*)$" ) { set $memcached_key "$1"; memcached_pass 192.168.6.2:11211; } expires 70; }这个配置会将http://xok.la/mem/abc指明到memcached的abc这个key去取数据。nginx目前没有写入memcached的任何机制,所以要往memcached里写入数据得用后台的动态语言完成,可以利用404定向到后端去写入数据。五、基于第三方插件ncachencache是新浪兄弟开发的一个不错的项目,它利用nginx和memcached实现了一部分类似squid缓存的功能,我并没有使用这个插件的经验,可以参考:http://code.google.com/p/ncache/
以上就介绍了Nginx缓存整理,包括了方面的内容,希望对PHP教程有兴趣的朋友有所帮助。