如何在Ubuntu14.04和Debian7上使用Varnish4加速Drupal7网站

来自菜鸟教程
跳转至:导航、​搜索

介绍

背景

Drupal 是最流行的免费开源内容管理系统之一。

由于它使用底层数据库来存储和检索内容页面、新闻项目、评论和博客文章等数据,因此 Drupal 需要大量的处理能力来提供单个页面视图。 每个页面展示都涉及启动 PHP 解释器、处理所有 Drupal 元素、访问数据库以获取信息、准备视觉布局以及为用户提供现成的内容。

这种密集的过程使得难以应对越来越多的人同时查看该网站。 由于每个访问者都需要不可忽略的处理能力,因此您的服务器资源很快就会成为瓶颈。

有很多方法可以适应增长和应对性能问题,其中大部分可以认为是缩放的方法。 软件方面的扩展被认为是系统适应增加的负载的能力,例如同时访问者数量的增加。

Varnish 通过添加有助于解决瓶颈的附加软件,帮助在软件级别进行扩展。

本文在 Ubuntu 14.04 上进行了测试,但应该可以在 Debian 7 上进行较小的路径更改。 它可能也适用于其他发行版,只需稍作更改。

清漆缓存

'Varnish 是一个缓存,这意味着它的作用是存储和记住 Web 应用程序在第一次访问内容时为用户提供的服务。 然后它可以再次为后续请求提供相同的内容 ',而无需再次询问 Web 应用程序。

它可用于提供静态内容,例如图像、脚本或样式表,因为 Varnish 速度极快,并且比 Apache 更好地处理流量。 也可用于缓存准静态内容; 也就是说,由应用程序动态生成的内容(使用数据库并花费大量时间准备),但在一段时间内保持不变,使内容适合缓存。

例如,当网站上的一篇文章发表时,它很少更新。 这样就完全没有必要在每次请求时都使用 Drupal 的所有处理点来计算和显示同一篇文章。 Varnish 完全不用联系 Drupal 就可以记住再次提供相同的页面。 这使得 Varnish 可以轻松地同时为 10、100 甚至 1000 人提供相同的内容 - 因为提供缓存页面需要非常少的处理能力。

在大多数情况下,使用 Varnish 可以使几乎所有网站都快得难以置信。 它还可以更轻松地应对突然的兴趣高峰(例如,当一篇非常受欢迎的文章发表时)。 所有这一切都转化为更快乐的访问者,他们可以更快、更可靠地交付他们的内容。

先决条件

本文假设您在 LAMP 上有一个基于 Drupal 的工作网站已经启动并运行。 以下是要求:

  • 一个 Ubuntu 14.04Debian 7 Droplet(在 Ubuntu 14.04 上测试)
  • 一个 sudo 用户
  • 德鲁巴

第 1 步 - 重新配置 Apache

默认情况下,Apache 监听端口 80。 这让 Apache 可以处理 Web 请求,例如 http://example.com 的浏览器 URL 请求。 要使用 Varnish,它必须能够处理这些请求。 首先,我们必须告诉 Apache 不再处理端口 80 上的请求。

更改 Apache 监听的端口

Apache 默认监听的端口在一个名为 ports.conf 的文件中设置,在 DebianUbuntu 上都位于在 /etc/apache2 中。

编辑文件:

sudo nano /etc/apache2/ports.conf

这将运行一个 nano 文本编辑器,显示该文件的默认内容,应该类似于以下内容。 更新 NameVirtualHostListen 行以使用端口 81

# If you just change the port or add more ports here, you will likely also
# have to change the VirtualHost statement in
# /etc/apache2/sites-enabled/000-default
# This is also true if you have upgraded from before 2.2.9-3 (i.e. from
# Debian etch). See /usr/share/doc/apache2.2-common/NEWS.Debian.gz and
# README.Debian.gz

NameVirtualHost *:81
Listen 81

<IfModule mod_ssl.c>
    # If you add NameVirtualHost *:443 here, you will also have to change
    # the VirtualHost statement in /etc/apache2/sites-available/default-ssl
    # to <VirtualHost *:443>
    # Server Name Indication for SSL named virtual hosts is currently not
    # supported by MSIE on Windows XP.
    Listen 443
</IfModule>

让我们按 CTRL+x,然后按 y,然后按 Enter 来保存文件。

更改虚拟主机的端口

默认情况下,全新的 Apache 安装在位于 /etc/apache2/sites-enabled/000-default 的配置文件中指定了一个虚拟主机。 如果您配置了多个虚拟主机,则必须修改其中的 all

要修改默认 Apache 虚拟主机的配置,我们输入:

sudo nano /etc/apache2/sites-enabled/000-default.conf

文件内容以如下行开头:

<VirtualHost *:80>
        ServerAdmin webmaster@localhost

和之前一样,我们必须将数字从 80 更改为 81

<VirtualHost *:81>
        ServerAdmin webmaster@localhost

使用 CTRL-x 后跟 yEnter 保存文件。

重新加载 Apache 配置

在这些更改之后,需要重新加载 Apache 配置:

sudo service apache2 reload

现在 Apache 将在新端口 81 上接受传入请求,而不是像以前那样在 80 上接受传入请求。

我们可以通过在浏览器中打开我们的网站来确认 - 如果不指定端口,它应该无法打开(如 http://example.com),但在将新端口添加到地址后正确显示(如http://example.com:81)。

我们现在已经准备好安装和配置 Varnish 以帮助我们使站点更快。

第 2 步 — 安装清漆

Debian 和 Ubuntu 都有带有 Varnish 的系统包,但我们建议使用由 Varnish 的作者制作的预构建包。 它将确保 Varnish 是最新的,这对于系统包来说是不正确的。

首先,确保安装了 apt-transport-https 包,它允许系统通过安全连接安装包:

sudo apt-get install apt-transport-https

这将安装必要的包或告诉我们它已经安装。

需要安装 Varnish 包服务器的公钥,以验证已安装包的真实性。 首先,切换到root

sudo su

添加密钥:

curl https://repo.varnish-cache.org/ubuntu/GPG-key.txt | apt-key add -

对于 Debian

echo "deb https://repo.varnish-cache.org/debian/ wheezy varnish-4.0" >> /etc/apt/sources.list.d/varnish-cache.list

对于 Ubuntu

echo "deb https://repo.varnish-cache.org/ubuntu/ trusty varnish-4.0" >> /etc/apt/sources.list.d/varnish-cache.list

您现在可以切换回您的 sudo 用户。

更新您的系统:

sudo apt-get update

安装清漆:

sudo apt-get install varnish

这将安装并运行 Varnish!

第三步——让 Varnish 监听 80 端口

默认情况下,Varnish 监听端口 6081。 我们将让 Varnish 在端口 80 上监听,接收来自我们网络用户的所有传入请求,就像 Apache 之前所做的那样。

让我们使用以下命令打开 Varnish 配置文件:

sudo nano /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.
# Use a 256MB memory based cache.
#
DAEMON_OPTS="-a :6081 \
             -T localhost:6082 \
             -f /etc/varnish/default.vcl \
             -S /etc/varnish/secret \
             -s malloc,256m"
             
. . .

更新 DAEMON_OPTS="-a: 行以使用端口 80 (记住也要保留 \):

. . .

DAEMON_OPTS="-a :80 \
             -T localhost:6082 \
             -f /etc/varnish/default.vcl \
             -S /etc/varnish/secret \
             -s malloc,256m"

. . .

使用 CTRL-xy 后跟 Enter 保存文件。

重新启动 Varnish 以使更改生效:

sudo service varnish restart

我们应该看到如下消息,没有错误:

[ ok ] Stopping HTTP accelerator: varnishd.
[ ok ] Starting HTTP accelerator: varnishd.

现在在浏览器中检查您的网站。 您将看到一个带有错误消息的白页,而不是以前可用的 Drupal 站点:

Error 503 Backend fetch failed

Backend fetch failed

Guru Meditation:
XID: 131081

Varnish cache server

这意味着 Varnish 已正确配置为接受传入连接,但还不能为我们的 Drupal 站点提供服务。 我们将在以下步骤中更改配置以使以前的 Drupal 站点重新联机。

清漆的工作原理

深入了解 Varnish 的一个很好的资源是官方的 Varnish Book,但我们将在这里介绍一些关于 Varnish 如何工作的基本事实。

如果您想立即完成安装并稍后了解更多信息,也可以跳到下一步。 但是,如果您了解 Varnish 的工作原理,您将对接下来的步骤有更深入的了解。

VCL 语言

Varnish 的配置是用一种叫做 VCL(Varnish 配置语言)的语言编写的。 它是一种简单的编程语言,由 Varnish 本身编译为本机 C 代码。

该配置由在处理传入 Web 请求的不同时刻执行的 methods 以及其余配置内容组成。

Varnish 在收到来自浏览器的请求时,但在处理请求之前执行一些指令,告诉它是将请求转发到实际应用程序,还是提供缓存的内容。 在这些说明中,可以操纵传入的请求、更改其内容或根据请求(URL、文件名、标头或 cookie)做出决定。

当 Varnish 决定从实际应用程序(在我们的例子中是 Drupal 网站)获取内容时,会执行其他指令。 这些指令可用于处理从应用程序接收到的内容。

当 Varnish 提供缓存内容而不从应用程序中重新检索它时,还会执行其他指令。

使用 VCL,可以构建一个复杂的逻辑,根据许多因素做出不同的缓存决策。 也可以构建一组非常简单的指令。

Varnish 为 all 提供了一个合理的默认实现,它的方法可以根据需要进行更改。 这意味着可以在配置中只指定 some 方法,即使那样,也只能指定 some 指令,其余的仍然依赖默认值。 这使得使用基本 Varnish 功能变得非常容易,同时可以在添加自定义指令时创建非常复杂的配置。

什么被缓存,什么不被缓存?

也许配置 Varnish 或任何其他缓存机制最困难的事情是决定 whenwhat 缓存。 大多数问题来自不正确的决定——缓存过多或不足。

对于典型的 Drupal 安装,这可能会导致两种不同的问题场景。

第一个是没有足够的页面被缓存,这使得 Varnish 几乎是不必要的。 它根本不会加快速度,因为大多数页面每次都是直接从 Drupal 应用程序中获取的。 这无助于解决性能问题,但也不会破坏任何东西。

第二个是缓存过多页面时。 在这种情况下,可能根本无法登录管理面板。 当为匿名和登录用户提供不同的内容时,访问者可能会获得旧的、无效的内容,甚至是混淆的内容。 在这种情况下,可能会破坏没有 Varnish 的情况下可以正常工作的东西。

让我们通过一些常见的因素来帮助我们决定 Varnish 是否会缓存内容。

Varnish 缓存一切

默认情况下,基本前提是Varnish缓存了everything。 Varnish 中的缓存是 exclusive,而不是 inclusive,这意味着除非您另行制定规则,否则所有内容都会被缓存。

请求方法

请求方法是请求的基本定义。 Varnish 默认缓存 only GETHEAD 请求,never 缓存其他类似 POST, PUT删除 。 这可以确保旨在对数据进行一些更改的请求完整地传递到应用程序而不会被缓存。

授权

默认情况下,对受密码保护的页面的请求根本不会被缓存。 这仅适用于使用 HTTP 基本授权 保护的页面。 Varnish 不知道特定于应用程序的机制,例如 Drupal 登录页面。 我们将不得不添加我们自己的规则以确保登录页面不会被缓存。

缓存标头

有时,Web 应用程序会在标头中返回它们自己的缓存信息。 Varnish 会考虑这些标头,因此当诸如 Drupal 之类的 Web 应用程序告诉 Varnish 永远不要缓存其响应时,除非我们在 VCL 文件中编写另一个行为,否则就会发生这种情况。 由于 Drupal 确实会发送自己的缓存信息,因此这将变得更加重要。

饼干

Cookie 可能是使用 Web 应用程序做出缓存决策的最重要和最困难的部分。

默认情况下,如果设置了请求响应cookie,则页面将而不是被缓存。 这是一个明智的决定,例如,登录用户由会话 cookie 识别。 如果缓存了带有 cookie 的页面,所有登录的用户将获得相同的内容,并且应用程序将无法区分用户。 然而,它也是最大的问题来源之一,因为 cookie 的使用很普遍。 请求中通常存在无害的 cookie,例如 Google Analytics 令牌,这些令牌根本不被应用程序使用,但也会使内容无法缓存。 如果没有仔细决定哪些 cookie 应该禁止缓存,哪些应该被忽略,那么对于今天的 Web 应用程序,我们最终将几乎没有缓存,因为有太多的 cookie 漂浮在周围。

Varnish 的 Drupal 特定配置的大部分片段将处理适当的 cookie 处理以删除不必要的 cookie 并允许缓存,但保留那些必要的,例如维护管理页面功能。

第 4 步 — 为 Drupal 配置 Varnish

对 Varnish 缓存的工作原理有了基本的了解,我们可以继续配置 Varnish 以与我们的 Drupal 站点一起工作。

让我们打开 Varnish VCL 配置文件:

sudo nano /etc/varnish/default.vcl

默认内容显示所有 Varnish 方法为空,这意味着默认值正在使用中。

我们可以添加自己的配置指令来实现必要的缓存策略。

第一个块指示 Varnish 如何联系后端 Web 服务器,在我们的例子中是安装了 DrupalApache。 我们将更改代码以反映我们用于配置 Apache 的端口 81

. . .

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

. . .

现在找到空占位符方法 vcl_recv

. . .

sub vcl_recv {
    # Happens before we check if we have this in cache already.
    #
    # Typically you clean up the request here, removing cookies you don't need,
    # rewriting the request, etc.
}

. . .

此方法中的代码在 Varnish 联系我们的 Drupal 站点之前执行 。 在这里,我们可以剥离来自浏览器的一些 cookie,对某些地址强制缓存(或不缓存),并做出第一个缓存决定。 我们将添加几个完成以下任务的规则:

  1. 在 Drupal 失败的情况下,允许 Varnish 提供陈旧(旧)的缓存内容。 即使 Drupal 没有响应,它也会使站点部分可用
  2. 确保根本没有缓存任何管理页面,迫使 Varnish 跳过某些 URL 的缓存
  3. 确保缓存静态文件——图像、脚本、样式表
  4. 去除 Drupal 正常工作所需的几个 cookie 以外的所有 cookie,包括用户登录功能

为了实现这一点,让我们将默认块替换为以下块。 以 # 开头的行是注释,不会被 Varnish 考虑在内,但在这里有助于使配置文件易于理解。 这整个块是新的,可以按原样粘贴:

. . .

sub vcl_recv {

    # Return (pass) instructs Varnish not to cache the request
    # when the condition is met.
    
    ## ADMIN PAGES ##
    
    # Here we filter out all URLs containing Drupal administrative sections
    if (req.url ~ "^/status\.php$" ||
        req.url ~ "^/update\.php$" ||
        req.url ~ "^/admin$" ||
        req.url ~ "^/admin/.*$" ||
        req.url ~ "^/user$" ||
        req.url ~ "^/user/.*$" ||
        req.url ~ "^/flag/.*$" ||
        req.url ~ "^.*/ajax/.*$" ||
        req.url ~ "^.*/ahah/.*$") {
           return (pass);
    }
    
    
    ## BACKUP AND MIGRATE MODULE ##
    
    # Backup and Migrate is a very popular Drupal module that needs to be excluded
    # It won't work with Varnish
    if (req.url ~ "^/admin/content/backup_migrate/export") {
        return (pipe);
    }
    
    ## COOKIES ##
    
    # Remove cookies for stylesheets, scripts, and images used throughout the site.
    # Removing cookies will allow Varnish to cache those files.
    if (req.url ~ "(?i)\.(css|js|jpg|jpeg|gif|png|ico)(\?.*)?$") {
        unset req.http.Cookie;
    }

    # Remove all cookies that are not necessary for Drupal to work properly.
    # Since it would be cumbersome to REMOVE certain cookies, we specify
    # which ones are of interest to us, and remove all others. In this particular
    # case we leave SESS, SSESS and NO_CACHE cookies used by Drupal's administrative
    # interface. Cookies in cookie header are delimited with ";", so when there are
    # many cookies, the header looks like "Cookie1=value1; Cookie2=value2; Cookie3..." 
    # and so on. That allows us to work with ";" to split cookies into individual
    # ones.
    #
    # The method for filtering unnecessary cookies has been adopted from:
    # https://fourkitchens.atlassian.net/wiki/display/TECH/Configure+Varnish+3+for+Drupal+7
    if (req.http.Cookie) {
        # 1. We add ; to the beginning of cookie header
        set req.http.Cookie = ";" + req.http.Cookie;
        # 2. We remove spaces following each occurence of ";". After this operation
        # all cookies are delimited with no spaces.
        set req.http.Cookie = regsuball(req.http.Cookie, "; +", ";");
        # 3. We replace ";" INTO "; " (adding the space we have previously removed) in cookies
        # named SESS..., SSESS... and NO_CACHE. After this operation those cookies will be 
        # easy to differentiate from the others, because those will be the only one with space
        # after ";"   
        set req.http.Cookie = regsuball(req.http.Cookie, ";(SESS[a-z0-9]+|SSESS[a-z0-9]+|NO_CACHE)=", "; \1=");
        # 4. We remove all cookies with no space after ";", so basically we remove all cookies other
        # than those above.
        set req.http.Cookie = regsuball(req.http.Cookie, ";[^ ][^;]*", "");
        # 5. We strip leading and trailing whitespace and semicolons.
        set req.http.Cookie = regsuball(req.http.Cookie, "^[; ]+|[; ]+$", "");
 
        # If there are no cookies after our striping procedure, we remove the header altogether,
        # thus allowing Varnish to cache this page
        if (req.http.Cookie == "") {
            unset req.http.Cookie;
        }
        # if any of our cookies of interest are still there, we disable caching and pass the request
        # straight to Apache and Drupal
        else {
            return (pass);
        }
    }
}

. . .

下一个方法是 vcl_backend_response。 此方法负责在将响应放入缓存或从缓存中丢弃之前处理来自 Apache 和 Drupal 的响应。 我们可以更改 Drupal 发送的内容以适应我们的缓存策略。

默认方法如下所示:

. . .

sub vcl_backend_response {
    # Happens after we have read the response headers from the backend.
    #
    # Here you clean the response headers, removing silly Set-Cookie headers
    # and other mistakes your backend does.
}

. . .

让我们用这个全新的块原样替换它。 评论包括:

. . .

sub vcl_backend_response {
    # Remove cookies for stylesheets, scripts and images used throughout the site.
    # Removing cookies will allow Varnish to cache those files. It is uncommon for
    # static files to contain cookies, but it is possible for files generated
    # dynamically by Drupal. Those cookies are unnecessary, but could prevent files
    # from being cached.
    if (bereq.url ~ "(?i)\.(css|js|jpg|jpeg|gif|png|ico)(\?.*)?$") {
        unset beresp.http.set-cookie;
    }
}

. . .

该代码使用与以前相同的选择文件的方法删除静态文件的 cookie,因此在 vcl_recvvcl_backend_response 中都删除了相同文件的 cookie。

让我们用 CTRL+x 保存配置文件,然后 yEnter。 无需更改其他方法。

第 5 步 - 重新启动清漆

重新启动 Varnish 以使更改生效:

sudo service varnish restart

Varnish 服务器应该重新启动而没有错误。

现在您应该可以在浏览器中再次查看您的 Drupal 网站了。

然而,在我们的 Drupal 站点被正确缓存之前,我们还需要多做一步。 我们需要在 Drupal 本身中启用缓存。

第 6 步 — 在 Drupal 中启用缓存

默认情况下,Drupal 禁用其缓存机制。 这导致标头被发送到 Varnish,从而强制页面根本不被缓存。 因此,禁用的 Drupal 缓存会自动阻止 Varnish 帮助我们加快站点速度。

要启用 Drupal 缓存,请以管理员身份登录您的 Drupal 站点。

选择配置菜单,然后选择性能

Performance 部分中,找到并检查 Cache pages for anonymous usersCache blocks 设置。

Minimum cache lifetimeExpiration of cached pages 设置为合理的值,例如 30 分钟 。 该值提供了相当大的性能增益,并且仍然确保缓存不会过时太久。 缓存生命周期的最佳设置取决于单个站点及其更新频率。 更改值后单击保存配置

这样就完成了使 Varnish 缓存我们的 Drupal 站点的必要配置。

第 7 步 - 验证清漆配置

为了确保 Varnish 正在缓存站点,我们可以使用名为 Is Varnish Working? 的简单工具。 在表格中输入您网站的地址。 您应该会看到如下响应:

如果您第一次收到“某种”消息,您可能需要检查两次。

延伸阅读

本文涵盖的主题只是冰山一角。 Varnish 是非常强大的软件,它不仅可以提供简单的缓存,还可以提供更多帮助。 官方的 Varnish 文档 是关于 Varnish 可能性和 VCL 语法的大量资源。 为了充分利用 Varnish 和 Drupal,最好了解 Drupal 在提高性能方面自身的可能性。 官方的 Drupal 性能文档 是一个很好的起点。

Varnish 是一个可以极大提升你网站性能的工具,但归根结底它并不是解决所有性能瓶颈的灵丹妙药,最好的结果是通过在各个阶段的精心规划来实现的。 话虽如此,即使是最简单的 Varnish 配置也可以在几分钟内使您的站点变得活泼。