搞这个博客本身就是当日记写的,也没打算多少访问量多少收入,甚至连一个广告都木有,但是wordpress在配置较低的vps上真的比较慢,所以最近折腾了好久,下面写一点经验吧。

起初我用的是wp super cache,但是理论上来讲,因为是文件系统缓存,所以这玩意依然需要读写磁盘,而且预缓存我反复测试都无法生效,而回收策略也总是莫名其妙,在没有更新的情况下,有时候几分钟就要重建缓存,有时候几个小时都不会,极其不稳定,所以放弃了。

然后试了一下w3 total cache,第一次用的是disk缓存,效果比较差,因为和super cache一样的,理论上只是减少了读数据库的次数,但读写磁盘依旧;第二次用了memcached做后端存储,效果还可以,但依旧感觉有时候会慢,因为我觉得,道理上来讲,判断是否重建缓存仍然需要跟数据库做对比,所以这两个方案都还差点。

昨天开始换成Super Static Cache,这下明显好得多,首页、单页和文章都会生成物理的html文件,速度飞快,不过感觉好像依然用了php进行过期判断,有时候稍微卡一下,而且一个让我很难受的是,这玩意不会生成目录的页面。

今天测试在Super Static Cache的基础上,在前端增加了varnish,因为这玩意是全内存缓冲,所以彻底解决了这些问题,而且可以将js、css、图片等所有静态文件都缓存起来,如果内存够用的话,可以完全避免读写磁盘了。我用自己的http调试工具反复测试多次,都能够正常缓存,访问速度飞快哦。

贴出我的varnish配置文件,然后我会简单解释一下重点:

# new 4.0 format.
vcl 4.0;

# Default backend definition. Set this to point to your content server.
backend default {
.host = "127.0.0.1";#后端web服务器的ip地址
.port = "8080";#后端web服务器的端口
.connect_timeout = 600s;
.first_byte_timeout = 600s;
.between_bytes_timeout = 600s;
.max_connections = 800;
}

# Only allow purging from specific IPs

#只允许本机进行清除缓存操作
acl purge {
"localhost";
"127.0.0.1";
}

sub vcl_recv {
set req.http.Host = regsub(req.http.Host, ":[0-9]+", "");

# 清除缓存操作的时候需要判断是否允许
if (req.method == "PURGE") {
# If not allowed then a error 405 is returned
if (!client.ip ~ purge) {
return(synth(405, "This IP is not allowed to send PURGE requests."));
}
return (purge);
}

# http验证和post方法不缓存
if (req.http.Authorization || req.method == "POST") {
return (pass);
}
# 不缓存 RSS feed
if (req.url ~ "/feed") {
return (pass);
}

# mu-开头的url不缓存
if (req.url ~ "/mu-.*") {
return (pass);
}
# wordpress的管理页面不缓存
if (req.url ~ "/wp-(login|admin)") {
return (pass);
}

# 不缓存 WooCommerce 页面
### REMOVE IT IF YOU DO NOT USE WOOCOMMERCE ###
if (req.url ~ "/(cart|my-account|checkout|addons|/?add-to-cart=)") {
return (pass);
}

# 删除"has_js" 的cookie
set req.http.Cookie = regsuball(req.http.Cookie, "has_js=[^;]+(; )?", "");

# 删除所有Google Analytics 的cookies
set req.http.Cookie = regsuball(req.http.Cookie, "__utm.=[^;]+(; )?", "");

# 删除Quant Capital 的cookies,一般是插件加进来的
set req.http.Cookie = regsuball(req.http.Cookie, "__qc.=[^;]+(; )?", "");

# 删除wp-settings-1 的cookies
set req.http.Cookie = regsuball(req.http.Cookie, "wp-settings-1=[^;]+(; )?", "");

# 删除wp-settings-time-1 的cookies
set req.http.Cookie = regsuball(req.http.Cookie, "wp-settings-time-1=[^;]+(; )?", "");

# 删除wp test 的cookies
set req.http.Cookie = regsuball(req.http.Cookie, "wordpress_test_cookie=[^;]+(; )?", "");

#允许cookie
if (req.http.cookie ~ "^ *$") {
unset req.http.cookie;
}

# 缓存这些文件名
if (req.url ~ "\.(css|js|png|gif|jp(e)?g|swf|ico)") {
unset req.http.cookie;
}

#这里,因为我所有的文章和分类都在这个目录,所以这一行就够了,如果你有多个,可以多复制几段
if (req.url ~ "/archives") {
unset req.http.cookie;
}

# 对这些文件类型试着进行gzip压缩
if (req.http.Accept-Encoding) {
if (req.url ~ "\.(jpg|png|gif|gz|tgz|bz2|tbz|mp3|ogg)$") {
unset req.http.Accept-Encoding;
} elsif (req.http.Accept-Encoding ~ "gzip") {
set req.http.Accept-Encoding = "gzip";
} elsif (req.http.Accept-Encoding ~ "deflate") {
set req.http.Accept-Encoding = "deflate";
} else {
unset req.http.Accept-Encoding;
}
}
# 检查cookie是不是wp的特别项
if (req.http.Cookie ~ "wordpress_" || req.http.Cookie ~ "comment_") {
return (pass);
}
if (!req.http.cookie) {
unset req.http.cookie;
}

# 所有其他的请求都缓存
return (hash);
}

sub vcl_pipe {
return (pipe);
}

sub vcl_pass {
return (fetch);
}

# 下面的没必要改动了
sub vcl_hash {
hash_data(req.url);
if (req.http.host) {
hash_data(req.http.host);
} else {
hash_data(server.ip);
}

# If the client supports compression, keep that in a different cache
if (req.http.Accept-Encoding) {
hash_data(req.http.Accept-Encoding);
}

return (lookup);
}

# This function is used when a request is sent by our backend (Nginx server)
sub vcl_backend_response {
# Remove some headers we never want to see
unset beresp.http.Server;
unset beresp.http.X-Powered-By;

# For static content strip all backend cookies
if (bereq.url ~ "\.(css|js|png|gif|jp(e?)g)|swf|ico") {
unset beresp.http.cookie;
}

# Only allow cookies to be set if we're in admin area
if (beresp.http.Set-Cookie && bereq.url !~ "^/wp-(login|admin)") {
unset beresp.http.Set-Cookie;
}

# don't cache response to posted requests or those with basic auth
if ( bereq.method == "POST" || bereq.http.Authorization ) {
set beresp.uncacheable = true;
set beresp.ttl = 120s;
return (deliver);
}

# don't cache search results
if ( bereq.url ~ "\?s=" ){
set beresp.uncacheable = true;
set beresp.ttl = 120s;
return (deliver);
}

# only cache status ok
if ( beresp.status != 200 ) {
set beresp.uncacheable = true;
set beresp.ttl = 120s;
return (deliver);
}

# 默认为缓存24小时
set beresp.ttl = 24h;
# Define the default grace period to serve cached content
set beresp.grace = 30s;

return (deliver);
}

# The routine when we deliver the HTTP request to the user
# Last chance to modify headers that are sent to the client
sub vcl_deliver {
if (obj.hits > 0) {
set resp.http.X-Cache = "cached";
} else {
set resp.http.x-Cache = "uncached";
}

# Remove some headers: PHP version
unset resp.http.X-Powered-By;

# Remove some headers: Apache version & OS
unset resp.http.Server;

# Remove some heanders: Varnish
unset resp.http.Via;
unset resp.http.X-Varnish;

return (deliver);
}

sub vcl_init {
return (ok);
}

sub vcl_fini {
return (ok);
}

读者有可能修改的地方我都做了中文注释,没必要改的地方最好别动。

根据配置文件的语法来看,未证实的推测是配置文件很接近脚本语言,是串行的,当所有前面的语句处理完以后会进入set beresp.ttl = 24h;这一行生效的地方,我这里设置的是24小时,也就是一天,其实这里设置一年都可以,因为Varnish HTTP Purge这个插件可以在有更新的时候清除对应的缓存,没更新的时候自然缓存了最好。安装上并且启用就可以了。

然后Super Static Cache的设置是direct模式,高级----缓存模式里面设置缓存所有内容。

now,现在的架构就是Super Static Cache根据需要来生成静态页面,由Varnish HTTP Purge在必要的时候通知前端varnish重建对应缓存,然后所有需要缓存的页面、图片等资源都会在前端varnish的内存中,完全内存读取,理论上已经到加速极限了。

完工了,初次访问到的文件是正常速度,以后再访问就是缓存结果了,而且据我测试,这个配置文件会试着对图片和css这些进行gzip压缩,传输速度会更快。

 

2016.08.14补充:

近期进行了较大调整,下面是完整的新版配置文件,需要静态的页面全缓存,所有动态(搜索、管理、订阅、站点地图)不缓存,一些特定的文件不缓存。

 

2016.09.18更新:经近期测试,Varnish HTTP Purge这个插件没用,更新插件看这篇文章: 《WordPress可支持Varnish 4.1的插件

Share

8 thoughts on “用Varnish+Super Static Cache+Varnish HTTP Purge给WordPress疯狂加速

    1. 不可能的,目前我们平民能买到的计算机存储系统里面,内存的效率是最高的,nginx不论如何都不会快于varnish的

  1. 您好,

    本人菜鸟,请教一下,按照您的方法,安装Super Static Cache以后,我选择的 Rewrite Mode (Recommend) 这个模式,在网站根目录生成了 Super-Static-Cache文件夹,里面有html文件。

    同时,varnish 按照您的最新版本设置的vcl,测试后发现,varnish 并没有缓存到Super-Static-Cache文件夹里的html信息,请问varnish 的 vcl 是不是应该特别设置下呢?如何设置?

    谢谢

    1. 我这不需要特别设置,连很多文章里提到的acl都没有搞就可以的……你说的没有缓存是怎么个情况?直接透传?还是miss?还是?
      按照我的配置文件的话,只要http头有age数值或者是hit状态,那就说明varnish已经缓存了,如果配置策略要求缓存,但实际上没有缓存的话,我知道的只有一个情况,就是内存不足,因为varnish是纯内存缓冲,所以如果系统可用物理内存达不到你给varnish配置的数额,同时过期策略又不允许清理掉较老的内容,那么可能会导致直接透传而不进行缓存,其他情况我还真没遇到过。补充,还有个情况就是任何文件第一次通过varnish都一定不会缓存的。

  2. 老大,我来第一个支持你哈。
    我浏览器开了2天还没关闭哈。
    我这几天也在折腾varnish 给wordpress加速在centos下。

发表评论

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