想象一下,你刚刚发布了一篇博文,并分享到了社交网络。然后,这篇文章恰巧被大V看中再次分享了出去,立即吸引了数百粉丝的目光,引导他们涌入了你的网站。看到这么多的访客量,以及它们的评论,你内心激动不已。突然之间,你的网站就挂掉了,满屏的数据连接错误……
或者假想另一种情境,你一直很努力地创业。突然有一天,一个大V在社交网络表达了对贵公司的喜爱之情,字里行间满满的赞叹。关注这个大V的粉丝心动了,又涌入了你的网站。不幸的是,点击连接后却无法进入你的网站,或者进入后无法注册用户,甚至页面相应超时,无法获取产品的序列号。尽管你在社交网络上对此非常诚恳的表达了歉意,但众多的浏览者都不会再有兴趣。
这些假想其实非常普遍。在我的工作中,就经常发现,当网站信息在社交网站流传开来的时候,移动设备的访问请求就会骤增。这也表明,在社交网络中,越来越多的人开始使用移动设备,而不是传统的桌面应用。此外,大多数的移动用户都在使用公共 Wi-Fi 以及其他低速网络来访问网站。所以,快速加载网站的任何优化措施,都会有利于用户的访问。
在本文中,我会向你介绍 Varnish 网页应用加速器(Varnish Web application accelerator)——这是一个免费、简单的工具,大大改善大规模突发性访问状态下的响应能力。
亮点
对于大多数的网站来说,众多用户请求访问的核心内容大都是一致的——尤其是每天都会更新内容的门户网站。不用多说你也会理解,图片、CSS 和 JavaScript,这些静态资源往往有较长的有效期(译者注:有利于在不同页面间复用)。但你可能没有深入思考过,通常在博客平台或者是内容管理系统中,响应用户的请求后,所返回的数据内容,大多也是相同的。
来自社交网络的用户进入一个博客后,并不会请求完全一致的信息。除了图片、JavaScript 和 CSS,这些信息还包括 PHP 动态生成的内容,以及从数据库查询到的数据。访问博客中的某一篇博文,所需要发送的每一条请求,不仅仅是在获取网络服务器提供的静态资源,还需要配合 PHP 脚本,使用数据库连接以及数据库表单检索等功能。
数据库连接的数量越多,Apache 需要处理的进程就会越多,而总的处理能力是由限度的。相应的,访客的数量越多,服务就会越不稳定,挣到的钱就会越少。
这就是类似 Varnish 的 HTTP 缓存发挥作用的地方。如此一来,从浏览器发出的请求,不再直接到达创建和维护网页的服务器,而是到达 HTTP 缓存服务器。如果缓存服务器中存在所需页面,那么直接从服务器的内存返回相应的资源,不再动用 Apache 服务器和数据库。如果所需页面不再缓存中,那么就像传统方式一样,使用 Apache 服务器来处理。Apche 处理完成之后,就会将这个页面保存到 HTTP 缓存服务器中,等到下一次请求相同页面时就可以直接返回了。
将页面保存在内存中,其响应速度远快于将其保存在硬盘中。此外,当请求的页面为于 HTTP 缓存服务器中时,就无需动用 PHP 或者数据库来处理相关操作。这也让 PHP 和 服务器能够有更多的性能来处理更繁重的进程和连接。比如,上面提到的被大 V 称赞的那家初创公司面临的情境,众多粉丝点击的链接其实只是网站中的少数几个页面——而这些完全可以保存在高速缓存服务器中,当需要时直接从内存响应请求。此时,准备注册的用户就会感到整个流程非常顺利,因为后台脚本和数据库连接的处理能力非常宽裕,完全不受突发性请求的影响。
原理
下面这个示意图,展示了 Apache 服务器响应请求后生成站点内容的基本流程。在这个例子中,为了请求相同的页面,一共从浏览器发送了五条指令给 Apache,而 Apache 很呆板的对每条请求都做了详细的处理。
是的,Apache 处理了每一条请求——图像,CSS,JavaScript 和 HTML 文件。如果 PHP 中有某个文件,就会解析一次。如果需要请求数据库的信息,那么就要执行一次数据连接,进行 SQL 查询等操作。最终,在 Apache 返回给浏览器信息之前,数据库返回相关信息组装成完成的页面。
如果我们在 Apache 之间使用 Varnish,我们就可以形成这样的一个流程:
如果浏览器请求的资源和页面已经存在缓存中,那么 Varnish 就会直接从内存返回这些资源,而 Apache、PHP 和 MySql 完全不需要进行重复的操作。如果浏览器请求的数据不再缓存中,那么 Varnish 就会将相关的处理工作转移给 Apache,让 Apache 处理相关的细节。这种方式的优势就在于,只让 Apache 处理必要的工作,一旦生成了所需的资源,该资源就会被保存到缓存服务器的内存中。当再次有请求访问这些资源时,Varnish 就完全有能力应付了。
这个工具还有另一项好处。在 Varnish 的属于中,你所配置的 Apache 服务器,被称为“处理后台”。Varnish 允许配置多个处理后台。所以,你可以同时运行两个网络服务器,比如,一台使用 Apache 处理 PHP 页面,一台使用 nginx 处理静态资源。在 Varnish 中设置成功后,就可以从正确的服务器获取相应的资源。在本篇教程中,我们将着眼于一个简单的示例。
震惊!快教我吧
安装和配置 Varnish 相当简单。你需要获得服务器的 root 权限(sudo),才能安装 Varnish。因此,你的网站需要托管在类似 VPS 的服务器上。现在 VPS 的价格也不是那么昂贵了,而且使用 Varnish 也会影响大家选择 VPS 而不是共享服务器。
有些 CMS 拥有的插件,可以直接使用 Varnish,或者将其整合进控制面板——通常可以更轻松地清空缓存。当然,你可以将 Varnish 融入任何的 CMS 或者静态网站中,而不需要特殊的配置。
在演示安装 Varnish 的整个流程之前,我会假设你已经在系统中使用 Apache 作为服务器了。虽然我在使用 Debian Linux,但安装过程中用到的软件包对其他分发版本也是适用的(只是系统中的文件路径会有所不同)。
在开始之前,先检查一下网站是否正常运行在 Apache 上。如果你使用的服务器是个新品,或者你想在本地虚拟机上尝试 Varnish,那么请确保配置一个虚拟主机,并可以用浏览器打开这个服务器的测试页面。
安装 Varnish
各个平台的详细安装说明请参考 Varnish 官方文档。因为我使用的是 Debian Wheezy,所以我会遵循 Debian 部分的说明。一旦 Varnish 安装完成,终端中就会输出下面这段话,提示你安装成功了:
代码如下:[ ok ] Starting HTTP accelerator: varnishd.
Apache 默认监听来自 80 端口的请求。这个端口接收请求,所以为了配合 Varnish 置于 Apache 之前的布局,需要修改端口,让 Varnish 监听 80 端口,同时将 Apache 的端口修改为一个与之不同的值——一般来说是 8080。然后在 Varnish 中配置相关信息,让 Varnish 连通 Apache。
重新配置 Apache
为了修改 Apache 当前的监听端口,需要使用 root 权限打开 /etc/apache2/ports.conf 文件,找到下面这两行:
代码如下: NameVirtualHost *:80
Listen 80
修改为:
代码如下:NameVirtualHost *:8080
Listen 8080
如果看到了下面这两行,只需要修改 80 为 8080 即可:
代码如下:NameVirtualHost 127.0.0.1:80
Listen 80
然后保存该文件并打开默认的虚拟主机文件,该文件应该在 /etc/apache2/sites-available。在这个文件中,找到下面这一行:
代码如下:<VirtualHost *:80>
修改为:
代码如下:<VirtualHost *:8080>
当然,你也需要修改其他用到的虚拟主机。
配置 Varnish
打开 /etc/default/varnish 文件,将页面滚动到没有注释、以 DAEMON_OPTS 开头的部分。将这一部分编辑如下,使 Varnish 监听 80 端口:
代码如下: DAEMON_OPTS="-a :80
-T localhost:1234
-f /etc/varnish/default.vcl
-S /etc/varnish/secret
-s malloc,256m"
打开 /etc/varnish/default.vcl 文件,检查默认的后台端口并设置为 8080,用来连通 Apache :
代码如下:backend default {
.host = "127.0.0.1";
.port = "8080";
}
在 root 权限下,使用如下命令重启 Apache 和 Varnish:
代码如下: service apache2 restart
service varnish restart
检查先前的测试页面是否仍然可以连接。如果可以,那么你可能想知道如何测试网站是否已经被缓存到了 Varnish 上。事实上有好几种方式,最简单的是使用 cURL。请在命令行中输入以下命令:
代码如下:curl http://yoursite.com --head
此时获得响应应该类似于 Via: 1.1 varnish。
你也可以查看由 Varnish 生成的静态资源。在终端中,输入 varnishstat,然后在浏览器中刷新页面,就会看到点击率逐渐增加。如果是由 Varnish 提供的资源,那么会标识为 hit;如果由 Apache 或其他后台提供,标识为 miss。
另一个有用的工具是 varnish-top。首先在命令行中输入 varnishtop -i txurl,然后在浏览器中刷新页面。这个工具将会显示哪些页面是由 Varnish 提供的。
清除缓存
当页面被缓存之后,当你改动 HTML 或者 CSS 文件,并不会立即看到更新的部分。这经常让我出差错。虽然我知道在 Apache 之前有个缓存服务器,但还是经常会犯傻“刚刚我的修改哪去了?”在命令行输入 varnishadm "ban.url ." 即可清除全部的缓存。
你也可以通过 HTTP 控制 Varnish。这方面有很多插件,比如服务于 WordPress 的 Varnish HTTP Purge,可以直接通过管理界面清除缓存。
自定义
也许,你会想通过了解一些 Varnish 的工作原理来微调它的配置。如果按照上述步骤配置 Varnish,一旦静态资源和页面被缓存到内存中,会逐渐积累起大量的静态资源和页面。
Varnish 只会缓存那些不会影响安全的资源,也因此有时不会缓存一些你认为会被缓存的资源,比如,cookies。
在默认配置中,如果设置了 cookie,那么 Varnish 就不会缓存相应的内容。所以,如果你的站点为不同用户提供不同的内容,比如个人资料,那么你肯定不会为了一个用户缓存所有人的资料。不过,有时你又会希望忽略一些 cookies,比如为了某些分析工作。如果网站并不提供任何个人资料,那么唯一需要考虑 cookies 的地方就是后台管理部分——如果 Varnish 缓存了后台管理的部分,那么查看修改就会非常不方便。
让我们修改一下 /etc/varnish/default.vcl 文件。假设你的后台管理部分在 /admin,那么你需要添加如下内容:
代码如下: sub vcl_recv {
if ( !( req.url ~ ^/admin/) ) {
unset req.http.Cookie;
}
}
有些 cookies 可能非常重要,比如已经登录的用户 cookies 就不应该缓存。所以,你就不会希望排除所有的 cookies。此处使用一个正则表达式可以定义那些 cookies 是我们需要的。也可以下哦那个网上找到很多解决这个问题的方案。对于分析工具的 cookies,你可以添加如下内容:
代码如下:sub vcl_recv {
// Remove has_js and Google Analytics __* cookies.
set req.http.Cookie = regsuball(req.http.Cookie, "(^|;s*)(_[_a-z]+|has_js)=[^;]*", "");
// Remove a ";" prefix, if present.
set req.http.Cookie = regsub(req.http.Cookie, "^;s*", "");
}
Varnish 文档中有一个专门的部分讲解 cookies。
在大多数情境下,按照上述配置 Varnish,并移除分析工具的 cookies,将会大大加快网站的访问速度。一旦 Varnish 建立并运行起来,在熟悉了配置的基础上,你就可以微调配置,从缓存规则中获得最佳性能。
进阶
更多资料,请参考 Varnish 官方文档。你应该从现在起尝试一些操作实例,深入了解 Varnish 的基础知识。