假设你用PHP和nginx搭建了自己的一个博客,这很棒。从服务器角度,每当有人访问了你的文章页面时,你的网站就会做一系列的、重复的任务,比如说获取一个几乎不怎么变化的文章内容。

假设访客A访问了这个文章页面,文章内容从数据库里获取了,包括图片、css、js等,都要从服务器加以获取。当访客B, C, D等访问了这同样一个没有做过内容改动的文章,同样的内容就会被服务器重复地获取,每次都要访问数据库,都要去找图片、css、js那些。

现在假设一天里那个页面有1,000,000 访问者,那么你的服务器就得处理1,000,000次访问,去供应那么多的资源,处理那么多的数据库查询,最终你的站点就会越来越慢,甚至停止响应,当服务器用光了工作进程或者连接的时候。

要避免这种情况,你就需要用上Varnish了。

准备工作

在进行下面的测试之前,你需要先有个linux系统,当然可以是本地的虚拟机,比如我们的vagrant homestead,也可以是线上服务器,当然如果是生产服务器,就需要提醒你特别小心咯。这里的测试用的是ubuntu,其它linux版本的细小差异在此不做赘述。

其次呢,你的这个服务器上最好有个nginx站点可以用来测试,当然了,用任何一个你的本地开发站点来测试就好了。

在继续进行之前,你可以用http-header-checker工具来查看一下你的站点,可以得到类似信息:

file

当然了,你也可以用任何喜欢的工具来查看header,这里我们varnish还没有运行,所以就看不到一个 “X-Varnish”的header,这个header暗示着当前网站是跑在varnish后面的。

安装Varnish

再简单不过了

sudo apt-get install -y varnish

当然如果你的系统里没有varnish的源,尤其是最新的varnish 5的,可以这样来添加源:

curl -L //packagecloud.io/varnishcache/varnish5/gpgkey | sudo apt-key add -
sudo apt-get update
sudo apt-get install -y apt-transport-https
sudo apt-get update
sudo apt-get install varnish

就好了,安装完以后,可以在下面两个目录里找到相应配置文件:

  1. /etc/default/varnish
  2. /etc/varnish/default.vcl

配置Varnish来监听80端口

默认呢,varnish监听的是6081端口,但我们的网站一般是在80端口,所以我们得改一下。

当然了,改之前,你可以用你的网站ip访问一下6081 端口,可以看到类似的varnish报错页面:

file

首先呢,我们改一下nginx的站点配置,让它不再使用80端口,以避免端口冲突。这里我的测试站点配置文件在/etc/nginx/sites-available/default里,你可以相应更改你自己的nginx配置:

server {
        listen 8080 default_server;
        listen [::]:8080 default_server;

        # Leave the other configuration items intact...
    }

我们让nginx站点默认监听8080端口,现在记得重新加载一下nginx好让配置生效:sudo service nginx reload,然后你再用ip或站点域名去访问8080端口,应该还能看见之前的测试站点页面。

接下来该更改varnish配置了,找到这个文件:/etc/default/varnish

 ## Alternative 2, Configuration with VCL
    #
    # Listen on port 6081, administration on localhost:6082, and forward to
    # one content server selected by the vcl file, based on the request.
    #
    DAEMON_OPTS="-a :6081 \
                 -T localhost:6082 \
                 -f /etc/varnish/default.vcl \
                 -S /etc/varnish/secret \
                 -s malloc,256m"

将其中的-a :6081 更改成 -a :80,这样呢就将varnish的前台监听端口设置到80端口了。

接下来呢,还要让varnish的后台去监听一下我们的站点,毕竟它要替我们从nginx站点里拉取内容,加以缓存,然后返回给前台。这个时候找到/etc/varnish/default.vcl这个配置文件

# Default backend definition. Set this to point to your content server.
    backend default {
        .host = "127.0.0.1";
        .port = "8080";
    }

可以看到默认的varnish后端,监听的就是我们的本地主机,而且端口就是8080,也即它能够从我们8080的nginx站点拉取内容。所以这里我们不需要更改什么,确认一下就好了。

添加varnish到系统服务中

接下来我们需要将varnish.service这个文件添加到系统服务中,这样我们可以用systemd 相关命令来在80端口开启varnish服务

$ sudo cp /lib/systemd/system/varnish.service /etc/systemd/system/
$ sudo nano /etc/systemd/system/varnish.service

上面,我们将varnish.service服务文件拷贝到了系统服务目录下,然后第二个命令是打开这个服务文件,默认是这样的:

ExecStart=/usr/sbin/varnishd -j unix,user=vcache -F -a :6081 -T localhost:6082 -f /etc/varnish/default.vcl -S /etc/varnish/secret -s malloc,256m

同样的,将里面-F -a :6081改成-F -a :80,里面的localhost:6082不用动,保存退出,然后执行下面的一系列命令,来重新加载一下系统服务,重启varnish和nginx:

$ sudo systemctl daemon-reload
$ sudo systemctl reload varnish.service
$ sudo service varnish restart
$ sudo service nginx restart

测试一下header,确保varnish正常运行

这个时候再访问我们的站点,检查header部分,应该能看到类似结果:

file

可以看到多了几个header:X-VarnishAgeVia,这些是varnish引入进来的,说明我们的varnish在运行了。

这个时候你再访问你的站点,你会发现,第一次访问过后,接下来的页面访问都会极其极其地快。当然这也取决于你的站点设置,如果你某个页面明确设置了不能缓存的Cache-Control header,那么默认varnish就不给你缓存这个页面,当然这些后期都可以具体更改调试。

那么正常情况下,你在开发者工具栏里会看到如下的性能表现:

file

可以看到传输数据很小,后面的资源直接从cache中加载,不需要请求时间了。

结论和进阶

Varnish是一个很伟大的开源缓存软件,使用恰当的话可以让你的网站极其、极其地快。当然了,缓存层永远是一把双刃剑,如果你使用不恰当,也会搞乱很多东西,让你茫然不知所措。Varnish呢既然是个强大的缓存代理软件,它肯定也就不单单我们上面展示的那么简单,是,你可以上面那样默认安装配置,就已经能给你带来不少性能提升,但是你要是想真正掌握好它,想真正发挥它的强大之处,那这些肯定是远远不够的,这里呢我们只是让大家初步体验,感受一下,便于进一步进阶。

想深入了解varnish的原理和机制,用最短的时间成为varnish高手,让你的生产环境的站点尽快体验上varnish,这里进一步推荐的资源就是我们的《【laravel国际会议】使用Varnish来构建应用“缓存层”和负载均衡》,这个是在laravel的国际会议laracon上,我们的主讲嘉宾Mattias分享了varnish相关的方方面面,让原本复杂恐怖的varnish缓存层,一下子变得简单和可操作起来。

  • 比如说你想学习如何清空varnish中的缓存,当你某个内容更新了以后;
  • 或者说你想更改varnish缓存的时间,或者想让你的网站即使挂掉了,用户依然无感知,依然能看到varnish缓存里的版本,这样你就有足够的时间去停机维护什么的;
  • 或者说你想单纯看看你的缓存命中率怎么样,是否大部分页面都重复用起了缓存;
  • 或者你某个页面,虽然后端的应用程序比如laravel,设置了说不要缓存,但你如何在varnish里还是缓存它呢?
  • 再或者,如何把一个页面,比如你的站点首页,分成很多个部分来缓存呢,比如你的页面导航栏,并不怎么经常改变,如何单独缓存这块呢?也即一个html页面,varnish都可以帮你拆分成不同部分来缓存,很神奇,不是吗?

当然了,更多的,请自行学习这个专场吧,别担心,虽然是英文大佬,但是我们都给你静心翻译,带上中文字幕了。

file

《【laravel国际会议】使用Varnish来构建应用“缓存层”和负载均衡》