上一篇文章分享了如何开启 Nginx 的缩略图功能,也提到了 Nginx 缩略图在完美替代七牛缩略图或 PHP 缩略图的同时,还会带来一定的 CPU 负载消耗。
因此,本文就来分享一下如何解决这个实时生成缩略图带来的 CPU 开销问题。
思路很简单,既然你要实时生成,那我就将你生成的缩略图缓存一份好了!在我测试期间发现,Nginx 的缓存也同样可以缓存伪静态的 html 页面,完全可以替代 WP-Super-Cache 这类缓存插件了。相信大部分 CDN 也是用的这个原理,比如百度云加速,我们可以在 header 里面发现一个 “Server:yunjiasu-nginx”的标识。
好了,废话不说,一起来看看如何实现吧!
一、代理模式
代理模式,即在使用 Nginx 反向代理时缓存指定内容,所用模块为 proxy_cache。这里网络上的很多教程会说,这个模式必须在反向代理中才能使用,说的好像不能用在只有一台服务器的情况似的。其实不然,我们用点小技巧,将 Nginx 本机的 80 端口代理转发到 本机的 8080 端口即可变相的开启反向代理模式,在这期间,就完全可以指定缓存内容了,且继续往下看!
①、下载模块
所用模块为 ngx_cache_purge,官方地址:http://labs.frickle.com/files/,我们可以挑选一个新版本下载到服务器上,比如 http://labs.frickle.com/files/ngx_cache_purge-2.3.tar.gz
cd /usr/local/src #下载 wget http://labs.frickle.com/files/ngx_cache_purge-2.3.tar.gz #解压 tar zxvf ngx_cache_purge-2.3.tar.gz
②、重新编译
所以先执行 -V 命令查看 Nginx 是否已经编译了该模块,
[[email protected]_Server ~]$ nginx -V Tengine version: Tengine/2.1.0 (nginx/1.6.2) built by gcc 4.4.7 20120313 (Red Hat 4.4.7-11) (GCC) TLS SNI support enabled configure arguments: --user=www --group=www --prefix=/usr/local/nginx --with-http_stub_status_module --with-http_gzip_static_module --with-http_concat_module --add-module=../ngx_cache_purge-2.3 --with-http_image_filter_module --add-module=../ngx_slowfs_cache-1.9 loaded modules: ngx_core_module (static) ngx_errlog_module (static) ...
如果编译参数中找不到 ngx_cache_purge,就需要重新编译 Nginx ,新增编译参数:
#注意第一步解压的文件夹和 nginx 源码在同一个目录 --add-module=../ngx_cache_purge-2.3
我现在用的是淘宝开放的 Tengine ,可以使用动态加载模块功能,如果是原版 Nginx ,可以参考张戈博客之前分享的文章,在原来的基础上加上上述参数重新编译 Nginx 即可:
③、新增配置
A. 在 http 上下文中新增缓存配置:
http { #以上略 ##cache## proxy_connect_timeout 5; proxy_read_timeout 60; proxy_send_timeout 5; proxy_buffer_size 16k; proxy_buffers 4 64k; proxy_busy_buffers_size 128k; proxy_temp_file_write_size 128k; proxy_temp_path /tmp/temp_cache1; #临时缓存目录 proxy_cache_path /tmp/cache1 levels=1:2 keys_zone=cache_one:200m inactive=30d max_size=5g; #设置缓存存放,不懂的参数自己百度搜索下 ##end## #以下略 .... }
Ps:上述配置中出现的目录,请在保存配置后,使用 mkdir 手动创建。
B. 如下修改网站原来的 server 模块:
server { #将之前监听修改成监听本地 8080,其他配置保持不变 listen 127.0.0.1:8080; server_name zhang.ge; #以下内容略... }
B. 如下新增一个反向代理 Server 模块,用于转发请求到本地 8080,变相实现反向代理模式:
server { listen 80; server_name zhang.ge; #缓存清理模块 location ~ /purge(/.*) { allow 127.0.0.1; allow 192.168.1.101; #此处表示允许访问缓存清理页面的 IP deny all; proxy_cache_purge cache_one $host$1$is_args$args; } #缓存 html 页面,可以缓存伪静态【这是亮点!】 location ~ .*\.html$ { proxy_pass http://127.0.0.1:8080; proxy_cache_key $host$uri$is_args$args; proxy_redirect off; proxy_set_header Host $host; proxy_cache cache_one; #状态为 200、302 的缓存 1 天 proxy_cache_valid 200 302 1d; #状态为 301 的缓存 2 天 proxy_cache_valid 301 2d; proxy_cache_valid any 1m; #浏览器过期时间设置 4 小时 expires 4h; #忽略头部禁止缓存申明,类似与 CDN 的强制缓存功能 proxy_ignore_headers "Cache-Control" "Expires" "Set-Cookie"; #在 header 中插入缓存状态,命中缓存为 HIT,没命中则为 MISS add_header Nginx-Cache "$upstream_cache_status"; } #图片缓存设置,如果不是使用了 Nginx 缩略图功能,这个可以不用,效果不明显 location ~ .*\.(gif|jpg|png|css|jsico)(.*) { proxy_pass http://127.0.0.1:8080; proxy_cache_key $host$uri$is_args$args; proxy_redirect off; proxy_set_header Host $host; proxy_cache cache_one; proxy_cache_valid 200 302 30d; proxy_cache_valid 301 1d; proxy_cache_valid any 1m; expires 30d; proxy_ignore_headers "Cache-Control" "Expires" "Set-Cookie"; add_header Nginx-Cache "$upstream_cache_status"; } #动态页面直接放过不缓存 location ~ .*\.(php)(.*){ proxy_pass http://127.0.0.1:8080; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } #设置缓存黑名单,不缓存指定页面,比如 wp 后台或其他需要登录态的页面,用分隔符隔开 location ~ ^/(wp-admin|system)(.*)$ { proxy_pass http://127.0.0.1:8080; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } #缓存以斜杠结尾的页面,类似于 CDN 的目录缓存,如果存在问题请取消缓存机制 location ~ ^(.*)/$ { proxy_pass http://127.0.0.1:8080; proxy_redirect off; proxy_cache_key $host$uri$is_args$args; proxy_set_header Host $host; proxy_cache cache_one; proxy_cache_valid 200 302 1d; proxy_cache_valid 301 1d; proxy_cache_valid any 1m; expires 1h; proxy_ignore_headers "Cache-Control" "Expires" "Set-Cookie"; add_header Nginx-Cache "$upstream_cache_status"; } location / { proxy_pass http://127.0.0.1:8080; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } }
全部保存后,执行 nginx -s reload 让配置生效即可。现在你再去访问网站的 html 页面,刷新一次就可以看到效果了!加载速度绝逼会有质的飞跃!而且你可以在 F12 开发模式的 Network 状态中看到 Nginx-Cache HIT 的标识!
④、清理缓存
清理缓存就有点麻烦了,我弄了多次也还是感觉不怎么好用!网上也有不少先驱分享了自动清理脚本或批量清理代码等。不过用了下也是不咋的好用。
还是说一下清理方法吧!在 A 部分的配置中,我们已经加入了 purge 缓存清理页面,假设一个 URL 为 http://192.168.1.1/test.html,通过访问 http://192.168.1.1/purge/test.html 就可以清除该 URL 的缓存(我实际测试经常是 404...)。
二、本地模式
第一种代理模式,我们是利用本地转发变相实现反向代理下的 Nginx 缓存功能,并且可以缓存 html 伪静态页面。从整体的配置可以看出,已经非常接近百度云加速等 CDN 的缓存功能了!对于理解 CDN 缓存还是有不小的帮助的!
现在分享一下,如果不用反向代理模式,该如何实现 Nginx 缓存呢?很简单,进一步借助 ngx_slowfs_cache 模块即可,这也是张戈博客在用模式,如何实现,且继续往下看。
①、下载模块
这个模式需要下载 2 个缓存模块:ngx_cache_purge 和 ngx_slowfs_cache 。这 2 个模块都出自一个网站,下载地址依然是 http://labs.frickle.com/files/ ,挑选一个最新版下载即可,比如:
http://labs.frickle.com/files/ngx_slowfs_cache-1.9.tar.gz
②、重新编译
和第一种模式一样,新增 2 个 --add-module 重新编译 Nginx 即可:
--add-module=../ngx_cache_purge-2.3 --add-module=../ngx_slowfs_cache-1.9
具体就不赘述了,参考上文和博客之前的分享就可以搞定了。
③、新增配置
I. 在 http 上下文新增如下配置:
http { #以上略 slowfs_cache_path /home/wwwroot/cache levels=1:2 keys_zone=fastcache:256m inactive=1d max_size=5g; slowfs_temp_path /tmp/nginx_temp_cache 1 2; #以下略 }
Ps:以上配置中所涉及的目录请手动创建。
II. 在 server 模块中新增如下配置:
#新增缓存清理配置 location ~ /purge(/.*) { allow 127.0.0.1; allow 192.168.1.101; deny all; slowfs_cache_purge fastcache $1; } #在上一篇文章的缩略图模块后新增缓存,让生成的缩略图缓存到磁盘(具体请看上一篇文章) location ~ .*\.(gif|jpg|jpeg|png|bmp)$ { set $width ''; set $height ''; set $width $arg_width; set $height $arg_height; if ( $width != '' ) { add_header Thumbnail "By Nginx"; } if ( $height = '' ) { set $height '-'; } if ( $width = '' ) { set $width '-'; set $height '-'; } image_filter resize $width $height; image_filter_buffer 5M; image_filter_jpeg_quality 80; image_filter_transparency on; #新增缓存配置 slowfs_cache fastcache; slowfs_cache_key $uri; slowfs_cache_valid 1d; #在 header 中插入缓存标识,比如:HIT/MISS from zhang.ge add_header X-Cache '$slowfs_cache_status from $host'; expires max; }
保存后,执行 nginx -s reload 重载 Nginx 即可。测试中发现,这种模式貌似无法缓存 html 伪静态页面,稍有遗憾,有兴趣的童鞋可以深入研究看看,可能是我没测试到位。
三、惯例总结
好了,通过以上折腾,我们已经完美的解决了 Nginx 实时生成缩略图带来的 CPU 开销问题了!而且,从代理模式的缓存中,我们甚至可以缓存 html 伪静态页面,这意味着什么?强迫症们有可以无情的丢弃一款 WordPress 缓存插件啦!不过,张戈博客暂时还是使用自己写的 php 代码来实现静态缓存,没有别的,主要是为了方便管理。
总体来说,对于 Nginx 的缩略图和缓存,我还是非常满意的,喜欢折腾的朋友也可以亲自试试,也许你能找到比本文更多的经验呢!
沙发
目前网站数据不大,还没有用到缓存来解决,收藏先! :grin:
有点臃肿了
呵呵
不错,可以提高网站速度,优化用户体验。。。
拿人嘴软,吃人手短,来冒个泡。。。
反正我收藏啦
非常有技术性的文章,受教了,支持博主!!!
很实用,很详细,收了!
太会折腾啦,我们不会折腾的只能用更高的配置资源来换取啦
确实不错。
貌似是真的快了些。
:evil: 你确定你用了?
我根本不懂技术,清理缓存已经是最大的技术含量了。。。 :evil:
https://zhang.ge/go/?url=http://labs.frickle.com/files/ngx_cache_purge-2.3.tar.gz,下载被屏蔽,搞这么高端,不会了。。
直接下载这个 http://labs.frickle.com/files/ngx_cache_purge-2.3.tar.gz
他这都不会,这篇文章建议最好不要折腾了,搞不好网站就挂了。。。
用ngx_cache_purge就搞了,配合nginx helper插件更新缓存
貌似非代理模式下不行吧?
可以的啊
网站包括官方给出的配置都是走proxy_cache,不在反向代理区域用这个指令确认可以吗?能否贴一下你成功通过的配置?参考下。
我是参考http://jybb.me/nginx-wordpress-fastcgi_cache-purge搞得
好东西,感谢分享,待会就试试。
搞成了吗?速度快了不少
已实施,感谢分享。
你这回复没刷新缓存啊
还有一层百度CDN缓,点击评论上的刷新按钮才能刷新。
不知道能不能分享下你的PHP优化代码(定制版)】
求份PHP优化代码(定制版),可以分享下不?
有Nginx缓存没必要在用php缓存html了。
代码在我博客就有分享:https://zhang.ge/4769.html
压缩
兄弟,多用用站内搜索
站内搜索下 压缩 不就有了??
这个嵌套真有意思,。
我也来嵌套一下~
这个对提高网站速度和用户体验不错哦
多级嵌套评论好恐怖啊
使用后nginx起不来了
Segmentation fault
试下最新的教程:https://zhang.ge/5042.html
确实挺深的!
第一次搞这个 在编译的时候显示 no such file or directory 应该进到哪开始编译啊,/usr/local/nginx/这里吗
编译失败怎么说。。。
博主你好,我也是tengine 为什么我编译后 还是没有加载执行 ./configure --add-module=../ngx_cache_purge-2.3 后还是没有加载 ngx_cache_purge模块呢。。。。。多谢。。
configure-->make-->make install
没搞定。。按照这个步骤,你现在还是用的tengine吗,ngx_cache_purge 可以装上 但是tengine就启动不了,,好像执行make install cp几个文件默认全部到nginx文件夹,复制覆盖到tengine 目录也不行。
大概知道为什么了,你编译的时候不能照搬文章参数,除了 那个 --add-module=../ngx_cache_purge-2.3 之外,其他的参数必须延续之前的 参数,比如安装路径! 你要是生搬硬套使用了--prefix=/usr/local/nginx,而实际路径是 /usr/local/tengine,肯定启动不了!实在不行,全部重新安装,先备份下配置文件即可。
tengine如何编译呢?
和nginx一模一样的编译
收藏
make: *** No rule to make target `build', needed by `default'. Stop.
按照你这个编译,出错...
编译语句,源码目录结构是什么样的?
谢谢分享 实在是太好用了
博主 发现了你的博客简直就是花光了我的幸运的感觉,内容太丰富了,全都是需要的,太棒了!收藏了还是置顶收藏的以后常来学习!
这篇文章我看完有个想法,我学你开启了fastcgi_cache 这个缓存的话,还需要按这篇文章设置嘛?会不会有冲突呢?
请问proxy_temp_path /tmp/temp_cache1; proxy_cache_path /tmp/cache1;按照这个配置是不是缓存的文件会保存在 /tmp/cache1目录里?为什么我测试了缓存已经生效,但是缓存目录文件里面都是空的?
对于全动态网站来说,缓存真的是用来救命的
https的网站,请问也是一样的么
大佬,宝塔的Nginx加速 是不是用的跟你这个一样的原理啊? !