第01章:Varnish 概述与架构
第01章:Varnish 概述与架构
1.1 Varnish 简介
Varnish Cache 是一款开源的高性能 HTTP 加速器(HTTP Accelerator),也称为反向代理缓存服务器(Reverse Proxy Cache)。它位于 HTTP 客户端和 HTTP 服务端之间,将后端服务器的响应缓存在内存中,从而显著提升网站的响应速度和并发处理能力。
核心特性
| 特性 | 说明 |
|---|---|
| 内存缓存 | 所有缓存对象存储在内存中,访问延迟极低(微秒级) |
| VCL 配置语言 | 使用专属的 Varnish Configuration Language 进行灵活配置 |
| 高并发 | 基于事件驱动架构,单实例可处理数万并发连接 |
| ESI 支持 | Edge Side Includes,支持页面片段缓存 |
| 热配置 | 支持不中断服务的情况下重新加载配置 |
| 丰富的 VMOD | 通过 Varnish Modules 扩展功能 |
| 内置管理接口 | 通过命令行管理接口实时管理缓存 |
1.2 发展历史
Varnish 的诞生与挪威最大的报纸网站 VG.no 密切相关。
版本演进
| 年份 | 版本 | 重要事件 |
|---|---|---|
| 2006 | Varnish 诞生 | Poul-Henning Kamp 为 VG.no 开发 |
| 2006 | 1.0 | 首个公开版本发布 |
| 2008 | 2.0 | 引入 VCL 2.0,支持更多子程序 |
| 2010 | 3.0 | ESI 支持增强,Director 改进 |
| 2011 | 3.0.2 | VCL 3.0,支持正则表达式 |
| 2014 | 4.0 | VCL 4.0,重大语法变更 |
| 2015 | 4.1 | VCL 4.1,改进 keep/grace 机制 |
| 2017 | 5.0 | 支持 HTTP/2 |
| 2019 | 6.0 | 长期支持版本,性能优化 |
| 2020 | 6.5 | VMOD 改进,TLS 增强 |
| 2021 | 7.0 | VCL 4.1 全面支持,新特性 |
| 2022 | 7.1-7.4 | 持续优化,安全修复 |
| 2024 | 7.5+ | 最新稳定版本 |
项目治理
Varnish Cache 由 Varnish Software 公司维护,采用 BSD 二开许可协议(BSD 2-Clause License),拥有活跃的开源社区和商业支持。
1.3 核心架构
Varnish 的架构设计围绕高性能和灵活性展开,采用事件驱动模型。
1.3.1 整体架构
┌─────────────┐ ┌─────────────────────────────────────────┐ ┌──────────────┐
│ │ │ Varnish Cache │ │ │
│ Client │────▶│ ┌─────────┐ ┌─────────┐ ┌─────────┐ │────▶│ Backend │
│ (Browser) │◀────│ │ Listener│→ │ VCL │→ │ Storage │ │◀────│ Server │
│ │ │ │ (accept)│ │ Engine │ │ Engine │ │ │ (Origin) │
└─────────────┘ │ └─────────┘ └─────────┘ └─────────┘ │ └──────────────┘
│ ┌─────────┐ ┌─────────┐ ┌─────────┐ │
│ │ Worker │ │ Hash │ │ Memory │ │
│ │ Threads │ │ Engine │ │ Manager │ │
│ └─────────┘ └─────────┘ └─────────┘ │
│ ┌─────────┐ ┌─────────┐ │
│ │ Session │ │ Log │ │
│ │ Manager │ │ Engine │ │
│ └─────────┘ └─────────┘ │
└─────────────────────────────────────────┘
1.3.2 关键组件
1. 监听器(Listener)
监听器负责接受来自客户端的 TCP 连接。Varnish 可以同时监听多个端口和地址。
2. VCL 引擎(VCL Engine)
VCL 引擎是 Varnish 的核心决策引擎。它执行 VCL 代码,决定如何处理每个请求:
- 是否使用缓存
- 如何修改请求/响应头部
- 选择哪个后端服务器
- 如何处理错误
3. 工作线程(Worker Threads)
Varnish 使用线程池模型处理请求,每个请求由一个工作线程处理。线程数量可配置:
# 查看线程池配置
varnishadm param.show thread_pool_min
varnishadm param.show thread_pool_max
4. 哈希引擎(Hash Engine)
哈希引擎根据请求的 URL、Host 等信息计算缓存键(Cache Key),用于在缓存中查找对象。
5. 存储引擎(Storage Engine)
Varnish 支持两种存储后端:
| 存储类型 | 说明 | 适用场景 |
|---|---|---|
-s malloc | 内存存储 | 默认方式,速度最快,重启后缓存丢失 |
-s file | 文件存储 | 使用 mmap 映射文件,重启后缓存保留 |
6. 日志引擎(Log Engine)
Varnish 使用共享内存环形缓冲区记录日志,支持实时查看和分析。
1.3.3 请求处理流程
当一个 HTTP 请求到达 Varnish 时,按以下顺序处理:
请求到达
│
▼
vcl_recv ← 接收请求,决定处理策略
│
├── lookup → 缓存查找(Hash Lookup)
│ │
│ ├── hit → vcl_hit → vcl_deliver → 返回响应
│ │
│ └── miss → vcl_miss → vcl_backend_fetch
│ │
│ ▼
│ 后端请求
│ │
│ ▼
│ vcl_backend_response
│ │
│ ▼
│ 缓存存储
│ │
│ ▼
│ vcl_deliver → 返回响应
│
├── pass → 直接传递到后端(不缓存)
│
├── pipe → 管道模式(直接转发字节流)
│
└── synth → 返回合成响应(错误页面等)
1.3.4 共享内存日志(VSM)
Varnish 使用共享内存段(Varnish Shared Memory, VSM)存储日志和统计信息,避免了磁盘 I/O 瓶颈:
# 查看 VSM 位置
ls -la /var/lib/varnish/
# 使用 varnishlog 查看实时日志
varnishlog -g request
# 使用 varnishstat 查看统计信息
varnishstat
1.4 与其他方案对比
1.4.1 Varnish vs Nginx 缓存
| 对比项 | Varnish | Nginx (proxy_cache) |
|---|---|---|
| 设计定位 | 专用 HTTP 缓存 | Web 服务器 + 缓存模块 |
| 配置语言 | VCL(专用语言,灵活强大) | 指令式配置(相对简单) |
| 缓存存储 | 内存为主 | 磁盘为主(支持内存) |
| 缓存清除 | 内置 Purge/Ban API | 需要第三方模块或手动删除 |
| ESI 支持 | 原生支持 | 需要第三方模块 |
| HTTP/2 | 支持 | 原生支持 |
| TLS 终结 | 需要 Hitch/外部代理 | 原生支持 |
| 学习曲线 | 较陡(需学习 VCL) | 较平缓 |
| 适用场景 | 高流量缓存加速 | 通用 Web 服务 + 缓存 |
选型建议
# 使用 Varnish 的场景:
# - 需要复杂的缓存策略
# - 高流量、高并发场景
# - 需要灵活的请求/响应修改
# - 需要 ESI 页面片段缓存
# 使用 Nginx 缓存的场景:
# - 已有 Nginx 基础设施
# - 缓存需求相对简单
# - 需要 TLS 终结 + 缓存一体化
# - 资源有限,不希望增加额外组件
1.4.2 Varnish vs CDN
| 对比项 | Varnish | CDN(如 Cloudflare、Akamai) |
|---|---|---|
| 部署位置 | 自建机房/服务器 | 全球分布式节点 |
| 成本 | 开源免费(自维护) | 按量付费 |
| 缓存控制 | 完全自定义 | 受限于提供商策略 |
| 边缘距离 | 仅限自建节点 | 靠近用户,延迟更低 |
| DDoS 防护 | 需额外方案 | 通常内置 |
| 配置灵活性 | 极高(VCL) | 有限(提供商 API) |
混合架构
在实际生产中,Varnish 和 CDN 经常配合使用:
用户 → CDN 边缘节点 → Varnish 集群 → 后端应用服务器
这种架构的优势:
- CDN 处理全球分发和 DDoS 防护
- Varnish 处理精细的缓存策略和动态内容缓存
- 后端专注于业务逻辑
1.4.3 Varnish vs Squid
| 对比项 | Varnish | Squid |
|---|---|---|
| 设计目标 | HTTP 反向代理缓存 | 正向/反向代理缓存 |
| 配置方式 | VCL(编程式) | squid.conf(指令式) |
| 内存使用 | 高效(虚拟内存) | 传统方式 |
| 性能 | 更高(事件驱动) | 较低(进程模型) |
| 缓存清除 | 灵活(Purge/Ban) | 有限 |
| 正向代理 | 不支持 | 支持 |
| 适用场景 | 反向代理/CDN 边缘 | 正向代理/内容过滤 |
1.5 适用场景
1.5.1 典型应用
1. 高流量网站加速
# 示例:电商首页缓存
sub vcl_recv {
if (req.url == "/" || req.url ~ "^/index") {
# 首页缓存 60 秒
set req.http.X-Cache-TTL = "60";
}
}
2. API 响应缓存
# 示例:REST API 缓存
sub vcl_recv {
if (req.url ~ "^/api/v1/products") {
# 产品列表 API 缓存 5 分钟
set req.http.X-Cache-TTL = "300";
}
}
3. 页面片段缓存(ESI)
# 示例:ESI 片段缓存
sub vcl_backend_response {
if (bereq.url ~ "^/fragment/") {
# ESI 片段缓存 5 分钟
set beresp.ttl = 5m;
set beresp.do_esi = true;
}
}
4. 静态资源缓存
# 示例:静态资源长缓存
sub vcl_recv {
if (req.url ~ "\.(css|js|jpg|png|gif|ico|woff2)$") {
# 静态资源缓存 7 天
set req.http.X-Cache-TTL = "604800";
}
}
1.5.2 不适用场景
| 场景 | 原因 |
|---|---|
| 实时聊天/WebSocket | Varnish 不支持长连接和 WebSocket |
| 流媒体大文件 | 内存缓存不适合超大文件 |
| 正向代理 | Varnish 设计为反向代理 |
| 需要 TLS 终结 | Varnish 本身不处理 TLS(需要配合 Hitch) |
| 动态个性化内容 | 个性化内容缓存命中率低 |
1.5.3 性能参考
在典型硬件上(16 核 CPU、64GB 内存),Varnish 的参考性能:
| 指标 | 参考值 |
|---|---|
| 缓存命中请求 | 100,000-200,000 req/s |
| 缓存未命中请求 | 20,000-50,000 req/s |
| 并发连接数 | 100,000+ |
| 响应延迟(命中) | < 1ms |
| 内存效率 | ~1KB 元数据/对象 |
1.6 Varnish 生态系统
1.6.1 核心组件
| 组件 | 说明 |
|---|---|
| varnishd | Varnish 主进程 |
| varnishadm | 管理命令行工具 |
| varnishlog | 实时日志查看工具 |
| varnishstat | 统计信息查看工具 |
| varnishtop | 日志排序工具 |
| varnishhist | 延迟直方图工具 |
| varnishncsa | NCSA 格式日志工具 |
| varnishtest | VCL 测试工具 |
1.6.2 相关项目
| 项目 | 说明 |
|---|---|
| Hitch | TLS 终结代理,与 Varnish 配合使用 |
| Varnish Agent | Varnish 管理代理,提供 REST API |
| Varnish Controller | Varnish 集群管理平台 |
| Varnish Broadcaster | 请求广播工具,用于集群缓存清除 |
| Varnish Custom Statistics | 自定义统计分析平台 |
1.7 注意事项
重要
- Varnish 默认不处理 TLS,生产环境需要配合 Hitch 或 Nginx 进行 TLS 终结
- Varnish 重启后内存缓存会丢失,需要预热(Warm-up)
- VCL 配置变更需要编译后才能生效,但不会中断服务
- 确保后端服务器正确设置 Cache-Control 头部,否则可能导致敏感信息被缓存
1.8 业务场景
场景一:电商网站
需求:首页、分类页、商品详情页需要快速响应
方案:
- 首页:缓存 60 秒
- 分类页:缓存 300 秒
- 商品详情页:缓存 600 秒,库存信息通过 AJAX 异步加载
- 购物车:不缓存(pass)
场景二:新闻资讯网站
需求:文章内容需要快速分发,热点文章高并发
方案:
- 文章页:缓存 300 秒,Grace 300 秒
- 热点列表:缓存 60 秒
- 评论区:ESI 片段缓存 30 秒
- 用户登录态:不缓存
场景三:API 网关
需求:REST API 响应加速,减少后端计算压力
方案:
- GET 请求:根据响应头缓存
- POST/PUT/DELETE:直接传递(pass)
- 特定 API:自定义缓存策略