Varnish缓存服务器的使用

= 1572

本文出自:【InTheWorld的博客】varnishcache (1)

我最早接触CDN的概念是看阿里“叔度”的分享,当时觉得CDN很有趣的。后来也看过一本移动研究院出的CDN书,但还是对CDN缺乏细致的了解。双十一的时候,趁着减价的时机,入手了一台阿里云的ECS服务器。这个blog的速度确实不敢恭维,所以昨天晚上开始着手给网站提提速。

刚开始我打算用LuManager来实现,后来又觉得LuManager这种面板操作确实有悖于自己学习的目的。而且,阿里上的这台ECS内存有两个G,感觉做一个内存层面的cache还是可以的。所以最终还是决定使用先玩一玩Varnish。Varnish这个软件其实挺出名的。

如果要说Varnish的原理,其实就是反向代理 + 内存缓存。大致的架构图如下图所示:

5243fbf2b2119313f8f3d19667380cd791238d67

我的web服务器是在西雅图,是一台相当低配的VPS,而反向代理服务器(即Varnish)则是一台阿里云的ECS,配置高于web服务器。反向代理的细节其实没太多需要解释的,在后边的配置中其实就可以感受到了。

Varnish的安装过程这里就不赘述了,主要说一下Varnish的配置过程。由于我使用的Varnish 4.0版本比较新,而恰好Varnish 4.0是有比较大的改动的,因此还是踩了几个的坑。Varnish的配置是使用VCL的,即Varnish Configuration Langurage。对于VCL,我其实也是没有认真的看过。但是作为配置脚本,VCL其实还是容易理解的。不过VCL 4.0有些需要注意的地方。

  1. vcl 4.0的标志,表明配置文件的版本;
  2. import directors,表示导入基本的子例程;
  3. vcl中使用了很多的子例程,这些例程都是Varnish声明好的;
  4. vcl各个子例程的逻辑关系如下图所示。

wKiom1NqVHSRED_tAAK8GTftr28587

在构造各个子例程的是,有一些常用的变量,它们即是子例程的操作对象。这些变量包括req, resp, bereq以及beresp。它们在Varnish中的作用如下图所示:

wKiom1NqVQeTaaG0AAH4p4fuFPM755

  • 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";
    }
}

最后看看效果吧!第一幅是没有使用静态缓存的,第二幅图是使用了静态资源缓存的。

image

image

从总的时间来看,并没有提升很多,这是由于这个页面比较小,不存在大量的静态资源。我本来应该贴一个复杂页面的对比图,奈何网站没有备案,改了dns之后很快被阿里云禁掉了,所以只能贴了这样一张图。然而从静态资源来看,比如这几张gif,它们的加载速度平均提升了10倍。Varnish毕竟是内存缓冲,而且服务器也在华东,所以快十倍也不奇怪。

总的来说,我这样的负载均衡其实还是挺低端的。一个比较大规模的负载均衡方案还是应该从dns做起,等到我的新域名备案成功后。打算在阿里云上,自己搭一个DNS + LVS这样的负载均衡系统。

同时,还有另外一个计划,就是用node.js写一个多功能站点。过去的两个周末都是在看MEAN.js这个框架,以前的node.js底子也比较浅,所以也算是复习一下了。要做的事好多!但是无论如何,享受并坚持!

 

参考资料:

Varnish 4.0 实战

仅有1条评论 发表评论

  1. Wu you /

    楼主厉害啊,以后我也要少玩游戏啦,再玩剁手

发表评论