使用 Varnish 和大量 RAM 优化繁忙的网站

使用 Varnish 和大量 RAM 优化繁忙的网站

[更新后更加简洁!]

我对针对大量流量的 Web 服务器进行优化还很陌生,但现在我正在尝试这个领域。

星期一,我们的网站服务器出现“slashdotted”现象——流量猛增(一小时内约有 85,000 名访客),尽管我们运行了 Varnish 和 nginx(它们工作正常),但 Apache 方面的情况确实很棘手,因为有些请求会生成一些动态内容。

服务器目前有 8GB RAM,很快将升级到 32GB,所以我确实需要 32GB 系统的配置帮助。当前运行的是 64 位 centos。

我已经研究了 varnish 和 nginx 设置,它们很好 - 合理的设置(静态内容由 nginx 直接提供,大量动态内容由 varnish 提供,如果它不在 varnish 中,则请求将传递给 apache。)

那么在 Apache 上,我们使用 MPM prefork 模块,每个 Apache 进程似乎都占用了大量的 RAM:

前三名:

S    48 20961  2965  0  75   0 187128 128307 ?    ?        00:05:25 httpd
S    48 20959  2965  0  75   0 249788 143435 ?    ?        00:05:55 httpd
S    48 18581  2965  0  75   0 314564 157747 ?    ?        00:06:40 httpd

倒数第 3 名:

S     0  2965     1  0  78   0 15132 89017 stext  ?        00:00:00 httpd
S    48 20947  2965  0  75   0 38492 93001 ?      ?        00:00:00 httpd
S    48 20945  2965  0  75   0 43300 93897 ?      ?        00:00:01 httpd

我不太确定,但我认为一个进程 = 一个客户端 = 一个人浏览器的一个连接。我想我的第一个问题是有人能证实这一点吗?是的,我们在同一台服务器上运行 php 和 zend 框架,MySQL 作为数据库后端。

当前配置(服务器当前有 8GB RAM):

MaxKeepAliveRequests 100

KeepAliveTimeout 2

<IfModule prefork.c>
StartServers       8
MinSpareServers    5
MaxSpareServers   20
ServerLimit      200
MaxClients       200
MaxRequestsPerChild  500
</IfModule>

我目前的想法是,在这种配置下,Apache 理论上可以在最坏的情况下尝试使用大约 63GB 的内存。例如 315MB 进程 * 200 maxclients = 大量内存。我不完全确定它是否能这样工作,但如果有人也能证实这一点,那会很有帮助!

我想做的是获得一些关于我应该注意哪些事情的建议 - 我们希望服务器能够随时处理另一波请求并利用我们获得的所有新 RAM。如果我自己无法弄清楚,我将在另一个问题中讨论如何优化 MySQL,但这里是 conf,以防万一会有所不同:http://pastebin.com/GbJU7AxY

多多加油!约翰。

答案1

每天 85,000 名访客到底是什么意思?独立访客、HTTP 总点击量,还是其他什么?

只要请求可以从缓存中得到满足,Varnish 就应该能够每秒处理数千次点击,而且占用很少的 CPU 和内存。尤其是在使用 Slashdotted 时,因为大多数人会寻找完全相同的内容。但它确实需要微调。默认情况下,它相当保守,因为它对通过的内容了解不多。它根据看到的标头和简单的规则集做出决定。例如,默认情况下,Varnish 会缓存对象 2 分钟,但前提是没有饼干存在于请求中,并且对象的 TTL 大于 0,等等。检查默认 VCL(特别是接收函数取值) 来确定默认逻辑,并确保您理解它。

因此,在您的域上设置单个 Google Analytics cookie 会导致所有请求传递到后端,即使 GA cookies 不是由您的后端服务器处理,而是由 Google 的 javascript 处理。WordPress 应用程序会设置各种 cookies,其中大多数仅适用于动态内容,这些 cookies 会在每次请求时由浏览器返回。如果您的页面包含 49 个静态资产和 1 个动态页面,则意味着这些静态资产都不会被缓存,因为请求包含您不关心的 cookie。只有动态请求上的 cookie 才能通过。这样的错误基本上会禁用 Varnish。此外,代码返回的各种缓存控制(和相关的)HTTP 标头也很重要。如果您的应用程序声称 Varnish 从后端检索的对象已过期,例如过去的 Expires 标头,Varnish 将不会缓存该对象。

换句话说,您需要调整应用程序以发出正确的标头,以便客户端(Varnish 和浏览器)可以缓存返回的内容。任何您无法在应用程序中更正的内容,您都可以在 Varnish 的 VCL 中覆盖。

例如,下面是我的代码,用于删除各种客户端跟踪 cookie,防止它们到达服务器。这属于vcl_recv

# Remove tracking cookies. The server doesn't need to see them.
if (req.http.Cookie) {
    # Remove has_js and Google Analytics __* cookies.
    set req.http.Cookie = regsuball(req.http.Cookie, "(^|;\s*)(_[_a-z]+|has_js|sifrFetch)=[^;]*", "");
    # Remove a ";" prefix, if present.
    set req.http.Cookie = regsub(req.http.Cookie, "^;\s*", "");
    # Remove cookie header if empty
    if (req.http.Cookie == "") {
        remove req.http.Cookie;
    }
}

类似地,我删除了某些路径的传入 cookie,以使这些请求可缓存:

if  ( req.url ~ "^/cms/cms_files/(?:css|img|js)/" ||  #CMS1
      req.url ~ "^/site_files/(?:css|img|imgc|js|swf|uploads|xml/.+\.xml$)" ||  #CMS1
      req.url ~ "^/(?:images|stylesheets|javascripts|swf|site_files/js_libs|site/image|favicon\.ico$|robots\.txt$)" ||  #CMS2
      ( req.http.host ~ "(?:shop\.example\.com|www\.example\.nl)"  &&  #Magento
        req.url ~  "^/(?:404|js|media|skin|favicon\.ico$)" ) || #Magento
) {
    unset req.http.cookie;
}

我在 vcl_fetch 中使用了类似的节,而unset beresp.http.cookie;不是,以防止后端在我不想要的路径上设置任何 cookie。

你可以添加一些调试头提供有关 varnish 如何处理请求的信息。使用 Firebug 查看这些内容,您将对您的应用有更多了解。另一个很好的信息来源是清漆书。例如,参见:https://www.varnish-software.com/static/book/VCL_Basics.html

我们的大部分动态内容缓存了 60 秒,足以抵御流量冲击。如果您需要一些单独的内容,但页面上的大部分内容都是静态的,请查看 Varnish 的静电放电(edge-side-includes) 允许您为页面的不同部分指定不同的缓存 TTL。

现在您已将后端请求减少到最低限度,请优化这些请求。分析您的应用程序,查找并修复问题。

你说得对: MaxClients x (maximum physical memory per Apache process) = (total memory Apache can use)

不过,这是物理内存,而不是您提到的虚拟内存。在顶部,水库列显示每个进程使用的物理内存。每个 Apache 进程都会增长到您的站点运行的最大脚本。将 MaxClients 限制为您的服务器可以处理的数量。接受您没有资源的请求是没有意义的。一旦您开始交换,您就输了。增加 Apache 预分叉的进程(服务器)数量,因为分叉是一项繁重的操作,您希望在它已经很忙时执行。ServerLimit 行是多余的。禁用 KeepAlive 或将其设置为 1-2 秒。

如果您提供许多静态资产,请考虑从 mod_php 切换到 PHP-FPM。这可让您的 Apache 进程保持轻量级。

相关内容