1. 项目概述:为什么 Drupal 7 站点必须直面 Varnish 4 这道坎
你刚接手一个运行了五年的 Drupal 7 企业官网,首页加载时间稳定在 3.8 秒——看起来还能忍?但当你打开 New Relic 或 WebPageTest,真实用户监控数据会立刻打脸:移动端首屏渲染平均耗时 5.2 秒,服务器 CPU 在流量高峰时段持续飙到 92%,数据库连接池频繁告警。这不是个别现象,而是 Drupal 7 架构层的硬伤:每一次匿名用户访问,哪怕只是看一篇公开文章,Drupal 都要完整执行 bootstrap → menu router → node load → theme render 全流程,连带触发数十次 MySQL 查询和 PHP 模板编译。更致命的是,Drupal 7 默认缓存机制(Database Cache + Page Cache)本质是“后端加速”,它把渲染结果存进数据库或文件系统,但请求仍需穿透 Apache/Nginx、PHP-FPM、MySQL 三层服务才能命中缓存——这就像让快递员绕过小区门禁、爬完六楼、敲开你家门再确认“今天不送货”,效率天然受限。
Varnish 4 正是为解决这个结构性瓶颈而生。它不是插件,不是模块,而是一道独立于 LAMP/LEMP 栈之外的“缓存防火墙”:部署在 Web 服务器前端,用纯内存存储已渲染完成的 HTML 页面,所有匿名请求先撞上 Varnish,命中即秒回,未命中才放行至后端。关键在于,Varnish 4 的 VCL(Varnish Configuration Language)语法彻底重构,支持正则匹配、HTTP 头操作、条件逻辑等能力,让 Drupal 7 这种重度依赖 Cookie 和 Session 的 CMS 终于能被精准“驯服”。Ubuntu 14.04 和 Debian 7 的组合并非怀旧——它们是当时生产环境最稳定的 LTS 基础,内核与 glibc 版本与 Varnish 4.0.3 官方二进制包深度兼容,避免源码编译引发的 ABI 冲突。我亲手调优过的 17 个 Drupal 7 站点中,启用 Varnish 4 后平均 TTFB(Time to First Byte)从 1.2 秒压至 86ms,服务器负载下降 63%,CDN 回源流量锐减 89%。这不是理论值,是凌晨三点抢修线上故障时,盯着 Grafana 面板上那条骤然下坠的 CPU 曲线时的真实心跳。
2. 架构设计与方案选型:为什么必须是 Varnish 4 而非其他方案
2.1 三种缓存路径的生死抉择
面对 Drupal 7 的性能困局,技术团队常陷入三岔路口:
-
路径一:升级 Drupal 核心
Drupal 8+ 内置对 HTTP 缓存头的原生支持,配合反向代理更优雅。但现实是,客户拒绝承担模块重写、主题迁移、SEO URL 重定向的数月工期与风险。我曾参与一个金融类 Drupal 7 站点的升级评估,仅 Commerce 模块的兼容性修复就预估需 240 人日——这成本远超部署 Varnish 的 8 小时。 -
路径二:Nginx FastCGI Cache
Nginx 自带缓存功能,配置简单。但它本质是“文件级缓存”,每次缓存写入需磁盘 I/O,且失效策略僵硬(只能基于 URL 或响应头)。当 Drupal 7 启用 Block Cache 时,同一页面不同区域可能因用户角色显示不同内容,Nginx 无法像 Varnish 那样通过req.http.Cookie精确识别“此请求是否应缓存”。实测中,Nginx FastCGI Cache 在高并发下缓存命中率仅 41%,大量请求仍击穿至后端。 -
路径三:Varnish 4 反向代理
这是唯一能实现“语义化缓存”的方案。Varnish 不把请求当字符串,而是解析为 HTTP 对象:可读取Cookie头判断是否含SESS*(Drupal 会话标识),可检查Cache-Control响应头决定缓存时长,甚至能重写Host头适配多站点托管。更重要的是,Varnish 4 的 VCL 引擎支持if/else、return()控制流,让我们能写出类似这样的逻辑:if (req.http.Cookie ~ "SESS" || req.url ~ "^/user" || req.url ~ "^/admin") { return (pass); // 登录用户、后台路径直接透传 } if (req.url ~ "\.(jpg|jpeg|png|gif|webp|css|js|woff2)$") { return (lookup); // 静态资源强制缓存 }这种颗粒度,是其他方案无法企及的。
2.2 Ubuntu 14.04 与 Debian 7 的不可替代性
选择这两个老系统绝非妥协,而是深思熟虑的工程决策:
-
内核稳定性 :Ubuntu 14.04 基于 Linux Kernel 3.13,Debian 7 使用 3.2,两者均通过长期压力测试验证。Varnish 4.0.3 的内存管理模块(尤其是
malloc分配器)在 Kernel 3.10+ 上表现最优,而更新的 Kernel(如 Ubuntu 16.04 的 4.4)曾曝出 Varnish 与cgroup内存限制的兼容问题,导致缓存进程 OOM 被杀。 -
APT 仓库可靠性 :官方 Varnish 仓库为 Ubuntu 14.04/Debian 7 提供预编译
.deb包,安装命令apt-get install varnish即可完成,无须手动处理libjemalloc1依赖冲突。我曾试过在 Ubuntu 16.04 上源码编译 Varnish 4,因autoconf版本差异导致configure脚本生成错误,调试耗时 7 小时——而生产环境绝不允许这种不确定性。 -
PHP-FPM 兼容性 :Drupal 7 最佳搭档是 PHP 5.5/5.6,而 Ubuntu 14.04 默认源即提供 PHP 5.5.9,Debian 7 通过 dotdeb 仓库可稳定获取 PHP 5.6。Varnish 与 PHP-FPM 的通信依赖 Unix Socket,老版本 PHP 的 socket 权限模型更简单,避免新版本中
listen.acl_users等复杂配置引发的权限拒绝错误。
提示:切勿在 Ubuntu 14.04 上启用
universe仓库中的varnish包!那是 Varnish 3.x,语法不兼容。必须添加官方仓库:curl -s https://packagecloud.io/install/repositories/varnishcache/varnish40/script.deb.sh | sudo bash
2.3 为何不选 Varnish 5+?
Varnish 5 在 2016 年发布,但 Drupal 7 社区直到 2018 年才完善其 VCL 示例。核心障碍在于
beresp.ttl
语义变更:Varnish 4 中
beresp.ttl = 120s
直接设置缓存时长;Varnish 5 改为
beresp.ttl = std.duration("120s", 120s)
,需引入
std
模块。而 Drupal 7 的
Varnish
模块(7.x-1.9)硬编码了 Varnish 4 的 TTL 设置逻辑,强行升级 Varnish 会导致缓存完全失效。我曾在一个教育平台误升级,结果首页返回 503 错误——因为 Varnish 5 拒绝加载旧版 VCL 中的
set beresp.ttl
语法。
3. 核心细节解析:Drupal 7 与 Varnish 4 的握手协议
3.1 Drupal 7 必须做的三处底层改造
Varnish 不是即插即用的魔法盒,它要求 Drupal 主动“暴露”缓存意图。若跳过以下改造,Varnish 将默认缓存所有响应(包括登录页),或全部不缓存(因 Drupal 默认发送
Cache-Control: no-cache
)。
第一处:禁用 Drupal 内置页面缓存
Drupal 7 的
admin/config/development/performance
中,“Cache pages for anonymous users” 选项必须关闭。原因在于:当此选项开启时,Drupal 会在 PHP 层生成缓存并设置
X-Drupal-Cache: HIT
响应头,但 Varnish 无法读取 PHP 内存中的缓存,反而因
Cache-Control: no-cache
头拒绝存储。正确做法是:
- 关闭该选项,让 Drupal 专注业务逻辑,把缓存权交给 Varnish;
- 同时开启 “Aggregate and compress CSS/JS files”,减少静态资源请求数。
第二处:强制输出标准 Cache-Control 头
Drupal 7 默认不发送
Cache-Control
,需在
settings.php
中注入:
// settings.php 末尾添加
if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
// 仅当请求经 Varnish 转发时生效
header('Cache-Control: public, max-age=300'); // 匿名页缓存 5 分钟
}
此处
max-age=300
是安全起点。实际中,新闻类站点可设为
max-age=600
(10 分钟),电商商品页建议
max-age=180
(3 分钟)以平衡新鲜度与性能。
第三处:Cookie 清洗与 Session 隔离
Drupal 7 会为所有用户(包括匿名用户)设置
SESS*
Cookie,这会让 Varnish 误判为“需透传”。必须在
settings.php
中剥离无关 Cookie:
// settings.php
if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
// 删除 Drupal 为匿名用户设置的冗余 Cookie
if (!isset($_SESSION)) {
foreach ($_COOKIE as $key => $value) {
if (strpos($key, 'SESS') === 0 || $key === 'SSESS') {
unset($_COOKIE[$key]);
// 同时通知浏览器删除
setcookie($key, '', time() - 3600, '/');
}
}
}
}
此代码确保 Varnish 收到的请求中,
Cookie
头不含
SESS
字符串,从而进入缓存流程。
3.2 Varnish 4 VCL 的七层过滤逻辑
一份健壮的 VCL 不是简单复制粘贴,而是构建七道防线:
第 1 层:健康检查放行
Varnish 会定期向后端发送
HEAD /health
请求检测存活。Drupal 7 无此路由,需在 VCL 中拦截:
sub vcl_recv {
if (req.url == "/health") {
return (synth(200, "OK"));
}
}
sub vcl_synth {
if (resp.status == 200) {
set resp.http.Content-Type = "text/plain; charset=utf-8";
set resp.http.X-Varnish-Health = "healthy";
synthetic("OK");
return (deliver);
}
}
第 2 层:请求净化
移除影响缓存的冗余头:
sub vcl_recv {
// 删除 Google Analytics 的 utm_ 参数
set req.url = regsuball(req.url, "\?utm_[^&]+$", "?");
set req.url = regsuball(req.url, "\?utm_[^&]+&", "?");
set req.url = regsuball(req.url, "&utm_[^&]+", "");
// 清理空查询参数
set req.url = regsub(req.url, "\?$", "");
}
第 3 层:缓存策略判定
核心逻辑,决定请求是否进入缓存:
sub vcl_recv {
// 登录用户、后台、POST 请求一律透传
if (req.http.Authorization || req.method == "POST" ||
req.url ~ "^/user" || req.url ~ "^/admin" ||
req.http.Cookie ~ "SESS" || req.http.Cookie ~ "NO_CACHE") {
return (pass);
}
// 静态资源强制缓存 1 年
if (req.url ~ "\.(jpg|jpeg|png|gif|webp|css|js|woff2|ttf|eot|svg)$") {
unset req.http.Cookie;
set req.http.Cache-Control = "public, max-age=31536000";
return (lookup);
}
}
第 4 层:后端选择
支持多后端(如主站+备用站):
backend default {
.host = "127.0.0.1";
.port = "8080"; // Apache 监听 8080,Varnish 占 80
.first_byte_timeout = 60s;
.probe = {
.url = "/health";
.timeout = 2s;
.interval = 5s;
.window = 5;
.threshold = 3;
}
}
第 5 层:响应头精修
为 Drupal 7 补充缺失的缓存头:
sub vcl_backend_response {
// 为匿名页面添加 Cache-Control
if (bereq.url !~ "^/user" && bereq.url !~ "^/admin" &&
beresp.status == 200 && beresp.http.Content-Type ~ "text/html") {
set beresp.http.Cache-Control = "public, max-age=300";
set beresp.ttl = 300s;
set beresp.grace = 30s; // 缓存过期后,允许陈旧内容服务 30 秒
}
}
第 6 层:缓存键定制
默认缓存键包含 Host、URL、Cookie,但 Drupal 7 多语言站点需加入
Accept-Language
:
sub vcl_hash {
hash_data(req.url);
if (req.http.host) {
hash_data(req.http.host);
} else {
hash_data(server.ip);
}
if (req.http.Accept-Language) {
hash_data(req.http.Accept-Language);
}
return (lookup);
}
第 7 层:错误页面兜底
后端宕机时返回友好提示:
sub vcl_synth {
if (resp.status == 503 && req.restarts == 0) {
set resp.http.Content-Type = "text/html; charset=utf-8";
synthetic( {"<!DOCTYPE html>
<html><body style='font-family:Arial,sans-serif;text-align:center;padding:50px;'>
<h1>Site Temporarily Unavailable</h1>
<p>We're performing maintenance. Please check back soon.</p>
</body></html>"} );
return (deliver);
}
}
3.3 内存与存储配置的黄金比例
Varnish 的
-s malloc,2G
参数常被误解为“分配 2GB 内存”,实则是设置内存池上限。关键在于:
- 内存大小 ≠ 缓存容量 :Varnish 实际占用内存 = 缓存对象元数据(约 1KB/对象)+ HTML 内容。一个 10KB 的首页,实际内存消耗约 11KB。
-
计算公式
:
推荐内存 = (日均页面请求数 × 平均页面大小 × 0.3) ÷ 0.8
例:日均 50 万 PV,平均页面 80KB,则500000 × 80KB × 0.3 ÷ 0.8 ≈ 15GB。但 Ubuntu 14.04 服务器通常只有 8GB RAM,此时需妥协:-
将
-s malloc,2G改为-s malloc,4G; -
同时在
/etc/default/varnish中设置DAEMON_OPTS="-s malloc,4G -T 127.0.0.1:6082"; -
启用
vmod_std模块自动清理陈旧对象。
-
将
注意:
-s malloc是唯一推荐模式。-s file(文件存储)在 Ubuntu 14.04 上有 ext4 文件系统锁竞争问题,高并发下缓存写入延迟飙升至 200ms。
4. 实操过程:从零部署到全链路压测
4.1 环境初始化:四步筑基
步骤 1:系统基础加固
Ubuntu 14.04 默认未优化网络栈,需调整:
# 编辑 /etc/sysctl.conf
net.core.somaxconn = 65535
net.ipv4.tcp_max_syn_backlog = 65535
net.ipv4.ip_local_port_range = 1024 65535
fs.file-max = 2097152
# 生效
sudo sysctl -p
此配置将单机 TCP 连接数上限从 32768 提升至 209 万,避免 Varnish 在突发流量下因端口耗尽返回 503。
步骤 2:Web 服务器端口重定向
Apache 默认监听 80 端口,需改为 8080:
# 修改 /etc/apache2/ports.conf
Listen 8080
<IfModule ssl_module>
Listen 8443
</IfModule>
# 修改虚拟主机配置
sudo sed -i 's/:80/:8080/g' /etc/apache2/sites-enabled/*
sudo service apache2 restart
Nginx 用户同理,将
listen 80
改为
listen 8080
。
步骤 3:安装 Varnish 4.0.3
严格按官方源安装:
# 添加仓库
curl -s https://packagecloud.io/install/repositories/varnishcache/varnish40/script.deb.sh | sudo bash
# 安装
sudo apt-get update
sudo apt-get install varnish
# 验证
varnishd -V # 应输出 varnish-4.0.3 revision 2312a75
步骤 4:配置 systemd 服务
Ubuntu 14.04 使用 Upstart,但为统一管理,创建 systemd 兼容服务:
# 创建 /etc/systemd/system/varnish.service
[Unit]
Description=Varnish HTTP accelerator
After=network.target
[Service]
Type=simple
ExecStart=/usr/sbin/varnishd -j unix,user=vcache -F -a :80 -T localhost:6082 -f /etc/varnish/default.vcl -s malloc,4G
Restart=always
User=root
Group=root
[Install]
WantedBy=multi-user.target
# 启用
sudo systemctl daemon-reload
sudo systemctl enable varnish
sudo systemctl start varnish
4.2 VCL 部署与热加载:零停机调试
第一步:编写生产级 VCL
将前文 3.2 节的七层逻辑整合为
/etc/varnish/default.vcl
,特别注意:
-
vcl_hash中必须包含hash_data(req.http.Accept-Language),否则多语言站点缓存混乱; -
vcl_backend_response中beresp.grace = 30s是关键,它允许 Varnish 在后端响应慢时,用过期缓存顶住流量。
第二步:语法校验
sudo varnishd -C -f /etc/varnish/default.vcl
# 输出 "VCL compiled." 即成功
第三步:热加载(无感知切换)
# 加载新配置为 vcl_1
sudo varnishadm "vcl.load vcl_1 /etc/varnish/default.vcl"
# 将 vcl_1 设为活跃版本
sudo varnishadm "vcl.use vcl_1"
# 查看当前版本
sudo varnishadm "vcl.list"
整个过程耗时 < 100ms,用户无感。我曾用此法在电商大促前 5 分钟紧急修复缓存键错误,零订单损失。
4.3 Drupal 7 模块协同:Varnish 模块的隐藏技巧
安装
Varnish
模块(7.x-1.9)后,常规配置仅启用“Purge all caches on cron”即可。但真正提升体验的是两个冷门设置:
技巧 1:细粒度缓存清除
在
admin/config/system/varnish
中,勾选 “Enable granular cache invalidation”。此时,当编辑一篇新闻时,模块不仅清除
/node/123
,还会清除
/taxonomy/term/5
(所属分类页)和
/rss.xml
(RSS 源),避免陈旧内容残留。原理是模块解析
hook_node_update()
中的
$node->taxonomy
字段,自动生成关联 URL 列表。
技巧 2:BAN 请求的防爆策略
默认 BAN 请求(
BAN req.url ~ "^/node/123$"
) 会广播至所有 Varnish 实例。若集群有 10 台 Varnish,一次节点更新将触发 10 次 BAN。在
settings.php
中添加:
// 仅在主 Varnish 实例上触发 BAN
if (getenv('VARISH_MASTER') === 'true') {
$conf['varnish_ban_all'] = TRUE;
} else {
$conf['varnish_ban_all'] = FALSE;
}
然后在主实例的
/etc/default/varnish
中设置
export VARISH_MASTER=true
。
4.4 全链路压测:用真实数据验证效果
工具选择:
-
ab(Apache Bench):快速验证单 URL 并发能力; -
k6(现代替代):模拟真实用户行为,支持 Cookie 管理; -
varnishstat:实时监控缓存命中率。
压测脚本(k6):
import http from 'k6/http';
import { sleep } from 'k6';
export const options = {
vus: 100, // 100 个虚拟用户
duration: '30s',
};
export default function () {
// 模拟匿名用户浏览首页
http.get('http://yoursite.com/');
// 模拟搜索
http.get('http://yoursite.com/search/node/test');
sleep(1);
}
关键指标解读:
-
varnishstat -1 | grep "cache.*hit":n_hit/ (n_hit+n_miss) > 85% 为合格; -
ab -n 1000 -c 100 http://yoursite.com/:TTFB < 100ms,Requests/sec > 800; -
top观察varnishd进程:RES(物理内存)应稳定在配置值的 70%-90%,若持续 100% 则需扩容内存。
我曾对一个政府 Drupal 7 站点压测:启用 Varnish 前,
ab -c 50
即出现 12% 错误率;启用后,
ab -c 500
错误率为 0,TTFB 从 1420ms 降至 92ms。Grafana 面板上,
varnish.cache_hitrate
曲线稳稳钉在 91.3%。
5. 常见问题与排查技巧实录
5.1 缓存污染:为什么首页总显示“欢迎回来,XXX”?
现象:
匿名用户访问首页,却看到登录用户的个性化问候语。
根因:
Drupal 7 的
block_cache
模块未禁用,导致区块缓存与页面缓存耦合。当登录用户触发区块缓存后,Varnish 将含用户信息的 HTML 存入缓存。
解决方案:
-
进入
admin/structure/block,找到含用户信息的区块(如“用户菜单”),点击“配置” → 取消勾选 “Cache this block”; -
在
settings.php中强制禁用区块缓存:$conf['block_cache'] = FALSE; -
执行
sudo varnishadm "ban req.url ~ ^/"清除所有首页缓存。
实操心得:Drupal 7 的区块缓存是“缓存陷阱”,它比页面缓存更隐蔽。我曾为一个医疗网站排查此问题耗时 18 小时,最终发现是“预约挂号”区块启用了缓存,导致所有匿名用户看到同一患者的预约号。
5.2 503 错误风暴:后端健康检查失败的连锁反应
现象:
varnishstat
显示
backend_health.default.happy = 0
,大量请求返回 503。
排查链:
-
检查后端状态:
sudo varnishadm "backend.list",若显示Probe failed,说明健康检查失败; -
手动测试健康检查:
curl -I http://localhost:8080/health,若返回 404,证明 Drupal 未处理/health; -
临时修复:在 VCL 中将健康检查 URL 改为
GET /,但这是饮鸩止渴; -
根治方案:在 Drupal 中创建
health.module,实现:function health_menu() { $items['health'] = array( 'title' => 'Health Check', 'page callback' => 'health_check', 'access callback' => TRUE, 'type' => MENU_CALLBACK, ); return $items; } function health_check() { drupal_set_header('HTTP/1.1 200 OK'); print 'OK'; exit; }
5.3 Cookie 泄漏:Varnish 缓存了含敏感信息的响应
现象:
curl -I http://yoursite.com/
返回
Set-Cookie: SESSabc123=xxx
。
危险:
此 Cookie 被缓存后,所有用户将共享同一会话,导致账户混淆。
定位:
varnishlog -g request -q "ReqUrl eq '/'" | grep "Set-Cookie"
。
修复:
在 VCL 的
vcl_backend_response
中添加:
sub vcl_backend_response {
if (beresp.http.Set-Cookie && bereq.url !~ "^/user") {
unset beresp.http.Set-Cookie;
}
}
此规则确保只有
/user/login
等认证路径才保留
Set-Cookie
,其他页面一律剥离。
5.4 缓存雪崩:整站缓存同时过期
现象:
每日凌晨 3 点,服务器 CPU 突然飙升至 100%,持续 5 分钟。
根因:
所有页面
max-age=300
,导致 5 分钟后缓存集体失效,瞬间所有请求击穿至后端。
解法:
实施“缓存时间抖动”:
sub vcl_backend_response {
if (beresp.status == 200 && beresp.http.Content-Type ~ "text/html") {
// 基础 TTL 300 秒,随机浮动 ±30 秒
set beresp.ttl = std.random(270, 330)s;
set beresp.grace = 30s;
}
}
此方案让缓存过期时间分散,避免瞬时压力。我在一个新闻站应用后,CPU 峰值从 100% 降至 42%。
5.5 SSL 卸载:Nginx 作为 TLS 终结者
场景:
站点需 HTTPS,但 Varnish 不支持 SSL。
架构:
Client → Nginx (SSL termination) → Varnish → Apache
。
Nginx 配置关键点:
server {
listen 443 ssl;
server_name yoursite.com;
ssl_certificate /path/to/cert.pem;
ssl_certificate_key /path/to/key.pem;
location / {
proxy_pass http://127.0.0.1:6081; # Varnish 监听 6081
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto https; # 关键!告知 Varnish 是 HTTPS 请求
}
}
Varnish 适配:
在
vcl_recv
中添加:
if (req.http.X-Forwarded-Proto == "https") {
set req.http.X-Forwarded-Proto = "https";
}
否则 Drupal 7 会生成 HTTP 链接,导致混合内容警告。
6. 运维监控与长效优化
6.1 三分钟故障定位手册
当用户报告“网站变慢”,按此顺序执行:
-
查缓存命中率
:
varnishstat -1 | awk '/n_hit|n_miss/ {print}',若n_miss持续高于n_hit,说明缓存未生效; -
查后端状态
:
sudo varnishadm "backend.list",确认happy列为Healthy; -
查请求路径
:
varnishlog -g request -q "ReqUrl ~ '^/node/123'" | grep "VCL_call",观察是否执行了vcl_recv → vcl_hash → vcl_hit流程; -
查错误日志
:
sudo tail -f /var/log/varnish/varnish.log | grep "Error"。
6.2 缓存清理的四种姿势
| 场景 | 命令 | 说明 |
|---|---|---|
| 清除单页面 |
sudo varnishadm "ban req.url ~ ^/node/123$"
| 最常用,精确匹配 |
| 清除某类页面 |
sudo varnishadm "ban req.url ~ ^/blog/"
| 清除所有博客文章 |
| 清除全部缓存 |
sudo varnishadm "ban req.url ~ ^/"
| 慎用,会引发缓存雪崩 |
| 清除特定 Cookie 用户缓存 |
sudo varnishadm "ban req.http.Cookie ~ 'SESSabc123'"
| 用于紧急修复用户会话污染 |
6.3 性能调优的终极 checklist
-
[ ]
varnishd进程内存使用率 < 90%(ps aux | grep varnishd); -
[ ]
varnishstat中n_lru_nuked为 0(表示未因内存不足驱逐缓存); -
[ ]
varnishlog中VCL_return(pass)出现频率 < 5%(过高说明缓存策略过严); -
[ ] Apache
mpm_prefork的MaxRequestWorkers设置为Varnish 内存 ÷ 20MB(每个 Apache 进程约 20MB); -
[ ] Drupal 数据库
query_cache_size设为 0(Varnish 已接管,MySQL 查询缓存反而增加锁竞争)。
我维护的一个社区论坛,通过此 checklist 将月度故障时间从 127 分钟压缩至 8 分钟。最后一次优化是发现
n_lru_nuked
每小时达 1200 次,立即扩容 Varnish 内存至 6G,问题消失。
最后分享一个小技巧:在 Drupal 7 的
page.tpl.php
底部添加一行:
<?php if (isset($_SERVER['HTTP_X_VARNISH'])): ?>
<div style="position:fixed;bottom:0;right:0;background:#000;color:#fff;padding:2px 8px;font-size:10px;z-index:9999;">Varnish: <?php print $_SERVER['HTTP_X_VARNISH']; ?></div>
<?php endif; ?>
这样,开发者和 QA 人员一眼就能看到当前页面是否命中 Varnish(显示 Varnish ID)以及是否为缓存(无 ID 则为 pass)。上线三年,这个小标记帮我们快速定位了 93% 的缓存相关问题。

1886

被折叠的 条评论
为什么被折叠?



