我最早接触CDN的概念是看阿里“叔度”的分享,当时觉得CDN很有趣的。后来也看过一本移动研究院出的CDN书,但还是对CDN缺乏细致的了解。双十一的时候,趁着减价的时机,入手了一台阿里云的ECS服务器。这个blog的速度确实不敢恭维,所以昨天晚上开始着手给网站提提速。
刚开始我打算用LuManager来实现,后来又觉得LuManager这种面板操作确实有悖于自己学习的目的。而且,阿里上的这台ECS内存有两个G,感觉做一个内存层面的cache还是可以的。所以最终还是决定使用先玩一玩Varnish。Varnish这个软件其实挺出名的。
如果要说Varnish的原理,其实就是反向代理 + 内存缓存。大致的架构图如下图所示:
我的web服务器是在西雅图,是一台相当低配的VPS,而反向代理服务器(即Varnish)则是一台阿里云的ECS,配置高于web服务器。反向代理的细节其实没太多需要解释的,在后边的配置中其实就可以感受到了。
Varnish的安装过程这里就不赘述了,主要说一下Varnish的配置过程。由于我使用的Varnish 4.0版本比较新,而恰好Varnish 4.0是有比较大的改动的,因此还是踩了几个的坑。Varnish的配置是使用VCL的,即Varnish Configuration Langurage。对于VCL,我其实也是没有认真的看过。但是作为配置脚本,VCL其实还是容易理解的。不过VCL 4.0有些需要注意的地方。
- vcl 4.0的标志,表明配置文件的版本;
- import directors,表示导入基本的子例程;
- vcl中使用了很多的子例程,这些例程都是Varnish声明好的;
- vcl各个子例程的逻辑关系如下图所示。
在构造各个子例程的是,有一些常用的变量,它们即是子例程的操作对象。这些变量包括req, resp, bereq以及beresp。它们在Varnish中的作用如下图所示:
- req:The request object,请求到达时可用的变量
- bereq:The backend request object,向后端主机请求时可用的变量
-
beresp:The backend response object,从后端主机获取内容时可用的变量
-
resp:The HTTP response object,对客户端响应时可用的变量
废话不多说,直接上我的最终配置。
# See the VCL chapters in the Users Guide at https://www.varnish-cache.org/docs/
# and http://varnish-cache.org/trac/wiki/VCLExamples for more examples.
# Marker to tell the VCL compiler that this VCL has been adapted to the
# new 4.0 format.
vcl 4.0;
import directors;
backend default {
.host = "192.168.1.22";
.port = "80";
}
sub vcl_recv {
if (req.url ~ "\.(php|asp|aspx|jsp|do|ashx|shtml)(|\?)") { return (pass); } if (req.url ~ "\.(css|js|bmp|png|gif|jpg|jpeg|ico)") { unset req.http.cookie; return (hash); } return (pass); } sub vcl_hash { hash_data(req.url); if (req.http.host) { hash_data(req.http.host); } else { hash_data(server.ip); } if (req.http.Cookie) { hash_data(req.http.Cookie); } if (req.http.Accept-Encoding ~ "gzip") { hash_data("gzip"); } elseif (req.http.Accept-Encoding ~ "deflate") { hash_data("deflate"); } } sub vcl_hit { if (req.method == "PURGE") { return(synth(200,"Purged")); } return (deliver); } sub vcl_miss { if (req.method == "PURGE") { return(synth(404,"Not in cache")); } return (fetch); } sub vcl_pass { if (req.method == "PURGE") { return(synth(502,"PURGE on a passed object")); } } sub vcl_backend_response { if (bereq.url ~ "\.(jpg|jpeg|gif|png)") {
set beresp.ttl = 7200s;
}
if (bereq.url ~ "\.(html|css|js)$") {
set beresp.ttl = 1200s;
}
if (beresp.http.Set-Cookie) {
return(deliver);
}
}
sub vcl_deliver {
if (obj.hits > 0) {
set resp.http.X-Cache = "HIT from " + server.ip;
} else {
set resp.http.X-Cache = "MISS";
}
}
最后看看效果吧!第一幅是没有使用静态缓存的,第二幅图是使用了静态资源缓存的。
从总的时间来看,并没有提升很多,这是由于这个页面比较小,不存在大量的静态资源。我本来应该贴一个复杂页面的对比图,奈何网站没有备案,改了dns之后很快被阿里云禁掉了,所以只能贴了这样一张图。然而从静态资源来看,比如这几张gif,它们的加载速度平均提升了10倍。Varnish毕竟是内存缓冲,而且服务器也在华东,所以快十倍也不奇怪。
总的来说,我这样的负载均衡其实还是挺低端的。一个比较大规模的负载均衡方案还是应该从dns做起,等到我的新域名备案成功后。打算在阿里云上,自己搭一个DNS + LVS这样的负载均衡系统。
同时,还有另外一个计划,就是用node.js写一个多功能站点。过去的两个周末都是在看MEAN.js这个框架,以前的node.js底子也比较浅,所以也算是复习一下了。要做的事好多!但是无论如何,享受并坚持!
参考资料:
楼主厉害啊,以后我也要少玩游戏啦,再玩剁手