Varnish配置基础 #
一、配置文件概述 #
1.1 配置文件位置 #
| 文件 | 位置 | 说明 |
|---|---|---|
| default.vcl | /etc/varnish/default.vcl | 主VCL配置文件 |
| secret | /etc/varnish/secret | 管理接口密钥 |
| varnish.params | /etc/varnish/varnish.params | 启动参数(RHEL系) |
1.2 配置层次结构 #
text
Varnish配置
├── 启动参数配置
│ ├── 监听端口
│ ├── 存储配置
│ └── 运行时参数
├── VCL配置
│ ├── 后端定义
│ ├── ACL定义
│ └── 子程序
└── 管理配置
├── 密钥文件
└── 管理端口
二、VCL语言基础 #
2.1 VCL版本声明 #
vcl
vcl 4.1;
VCL版本说明:
| 版本 | Varnish版本 | 特性 |
|---|---|---|
| 4.0 | 4.x | 基础VCL |
| 4.1 | 6.x+ | 增强特性、新变量 |
2.2 注释语法 #
vcl
# 这是单行注释
// 这也是单行注释
/*
* 这是多行注释
* 可以跨越多行
*/
2.3 基本语法规则 #
vcl
vcl 4.1;
# 语句以分号结尾
set req.http.X-Custom = "value";
# 字符串使用双引号
set req.http.Host = "example.com";
# 正则表达式使用斜杠
if (req.url ~ "\.(css|js)$") {
return (hash);
}
# 条件语句
if (req.method == "GET") {
return (hash);
} elseif (req.method == "POST") {
return (pass);
} else {
return (synth(405, "Method Not Allowed"));
}
2.4 数据类型 #
| 类型 | 说明 | 示例 |
|---|---|---|
| STRING | 字符串 | “hello” |
| INT | 整数 | 3600 |
| DURATION | 时间间隔 | 1h, 30m, 60s |
| IP | IP地址 | “192.168.1.1” |
| BOOL | 布尔值 | true, false |
| REGEX | 正则表达式 | “.css$” |
| HEADER | HTTP头 | req.http.Host |
2.5 运算符 #
vcl
# 比较运算符
== # 等于
!= # 不等于
< # 小于
> # 大于
<= # 小于等于
>= # 大于等于
# 逻辑运算符
&& # 与
|| # 或
! # 非
# 正则匹配
~ # 匹配
!~ # 不匹配
三、后端配置 #
3.1 基本后端定义 #
vcl
vcl 4.1;
backend default {
.host = "127.0.0.1";
.port = "8080";
}
3.2 后端参数详解 #
vcl
backend default {
# 必需参数
.host = "127.0.0.1"; # 后端主机地址
.port = "8080"; # 后端端口
# 可选参数
.host_header = "example.com"; # Host头
.connect_timeout = 5s; # 连接超时
.first_byte_timeout = 90s; # 首字节超时
.between_bytes_timeout = 2s; # 字节间超时
.max_connections = 300; # 最大连接数
.proxy_header = 1; # PROXY协议版本
}
3.3 多后端配置 #
vcl
backend static {
.host = "192.168.1.10";
.port = "80";
}
backend api {
.host = "192.168.1.20";
.port = "8080";
}
sub vcl_recv {
if (req.url ~ "^/api/") {
set req.backend_hint = api;
} else {
set req.backend_hint = static;
}
}
四、ACL配置 #
4.1 定义ACL #
vcl
acl purge {
"localhost";
"192.168.1.0"/24;
!"192.168.1.100";
}
acl admin {
"10.0.0.0"/8;
}
4.2 使用ACL #
vcl
sub vcl_recv {
if (req.method == "PURGE") {
if (!client.ip ~ purge) {
return (synth(405, "Not allowed."));
}
return (purge);
}
}
五、子程序详解 #
5.1 子程序概览 #
| 子程序 | 触发时机 | 主要用途 |
|---|---|---|
| vcl_init | VCL加载时 | 初始化VMOD |
| vcl_recv | 接收请求 | 请求处理、路由 |
| vcl_pipe | 管道模式 | 直接转发 |
| vcl_pass | 跳过缓存 | 直接请求后端 |
| vcl_hash | 计算缓存键 | 自定义缓存键 |
| vcl_hit | 缓存命中 | 处理命中响应 |
| vcl_miss | 缓存未命中 | 处理未命中请求 |
| vcl_backend_fetch | 请求后端 | 修改后端请求 |
| vcl_backend_response | 后端响应 | 处理后端响应 |
| vcl_backend_error | 后端错误 | 处理后端错误 |
| vcl_deliver | 返回响应 | 修改返回响应 |
| vcl_synth | 合成响应 | 自定义错误页面 |
| vcl_fini | VCL卸载时 | 清理资源 |
5.2 vcl_recv #
vcl
sub vcl_recv {
# 标准化请求方法
if (req.method != "GET" &&
req.method != "HEAD" &&
req.method != "PUT" &&
req.method != "POST" &&
req.method != "TRACE" &&
req.method != "OPTIONS" &&
req.method != "DELETE") {
return (pipe);
}
# 非GET/HEAD请求不缓存
if (req.method != "GET" && req.method != "HEAD") {
return (pass);
}
# 移除Cookie以缓存静态资源
if (req.url ~ "\.(css|js|png|gif|jpg|jpeg|ico|svg|woff|woff2)$") {
unset req.http.Cookie;
return (hash);
}
# 带Cookie的请求不缓存
if (req.http.Cookie) {
return (pass);
}
return (hash);
}
5.3 vcl_backend_response #
vcl
sub vcl_backend_response {
# 设置缓存时间
if (beresp.ttl <= 0s) {
set beresp.ttl = 5m;
}
# 静态资源缓存更长时间
if (bereq.url ~ "\.(css|js|png|gif|jpg|jpeg|ico|svg)$") {
set beresp.ttl = 1d;
unset beresp.http.Set-Cookie;
}
# 动态内容短缓存
if (beresp.http.Content-Type ~ "text/html") {
set beresp.ttl = 5m;
}
# 不缓存带Set-Cookie的响应
if (beresp.http.Set-Cookie) {
set beresp.uncacheable = true;
set beresp.ttl = 0s;
}
}
5.4 vcl_deliver #
vcl
sub vcl_deliver {
# 添加缓存状态头
if (obj.hits > 0) {
set resp.http.X-Cache = "HIT";
set resp.http.X-Cache-Hits = obj.hits;
} else {
set resp.http.X-Cache = "MISS";
}
# 移除敏感头
unset resp.http.X-Powered-By;
unset resp.http.Server;
# 添加调试信息
if (req.http.X-Debug) {
set resp.http.X-Varnish-Debug = "enabled";
}
}
六、内置变量 #
6.1 请求变量 (req.*) #
| 变量 | 说明 |
|---|---|
| req.url | 请求URL |
| req.method | 请求方法 |
| req.http.* | 请求头 |
| req.proto | HTTP协议版本 |
| req.restarts | 重启次数 |
| req.xid | 请求ID |
6.2 后端请求变量 (bereq.*) #
| 变量 | 说明 |
|---|---|
| bereq.url | 后端请求URL |
| bereq.method | 后端请求方法 |
| bereq.http.* | 后端请求头 |
| bereq.connect_timeout | 连接超时 |
| bereq.first_byte_timeout | 首字节超时 |
6.3 后端响应变量 (beresp.*) #
| 变量 | 说明 |
|---|---|
| beresp.status | 响应状态码 |
| beresp.http.* | 响应头 |
| beresp.ttl | 缓存TTL |
| beresp.grace | 宽限时间 |
| beresp.uncacheable | 是否不可缓存 |
6.4 响应变量 (resp.*) #
| 变量 | 说明 |
|---|---|
| resp.status | 响应状态码 |
| resp.http.* | 响应头 |
| resp.proto | HTTP协议版本 |
6.5 对象变量 (obj.*) #
| 变量 | 说明 |
|---|---|
| obj.status | 对象状态码 |
| obj.http.* | 对象头 |
| obj.ttl | 对象TTL |
| obj.hits | 命中次数 |
| obj.grace | 宽限时间 |
6.6 客户端变量 (client.*) #
| 叱量 | 说明 |
|---|---|
| client.ip | 客户端IP |
| client.identity | 客户端标识 |
七、返回状态 #
7.1 vcl_recv返回值 #
| 返回值 | 说明 |
|---|---|
| hash | 计算缓存键,查找缓存 |
| pass | 跳过缓存,直接请求后端 |
| pipe | 管道模式,直接转发 |
| purge | 清除缓存 |
| synth | 返回合成响应 |
| vcl | 切换到其他VCL |
7.2 vcl_backend_response返回值 #
| 返回值 | 说明 |
|---|---|
| deliver | 缓存并返回响应 |
| retry | 重试后端请求 |
| abandon | 放弃请求 |
7.3 vcl_deliver返回值 #
| 返回值 | 说明 |
|---|---|
| deliver | 返回响应 |
| retry | 重试 |
八、启动参数配置 #
8.1 存储配置 #
bash
# 内存存储
-s malloc,1G
# 文件存储
-s file,/var/lib/varnish/storage.bin,2G
# 混合存储
-s malloc,512m -s file,/var/lib/varnish/storage.bin,1G
存储参数说明:
| 参数 | 说明 |
|---|---|
| malloc | 内存存储 |
| file | 文件映射存储 |
| 大小 | 支持K/M/G单位 |
8.2 线程配置 #
bash
# 线程池配置
-p thread_pool_min=50
-p thread_pool_max=500
-p thread_pool_timeout=300
-p thread_pools=2
线程参数说明:
| 参数 | 默认值 | 说明 |
|---|---|---|
| thread_pools | 2 | 线程池数量 |
| thread_pool_min | 100 | 最小线程数 |
| thread_pool_max | 5000 | 最大线程数 |
| thread_pool_timeout | 300 | 空闲线程超时 |
8.3 内存配置 #
bash
# 工作区内存
-p http_resp_size=64k
-p http_req_size=32k
-p workspace_backend=64k
-p workspace_client=64k
8.4 超时配置 #
bash
# 连接超时
-p connect_timeout=3.5
-p first_byte_timeout=60
-p between_bytes_timeout=60
九、运行时参数 #
9.1 查看参数 #
bash
# 查看所有参数
varnishadm param.show
# 查看特定参数
varnishadm param.show thread_pool_max
# 查看参数说明
varnishadm param.show -l thread_pool_max
9.2 动态修改参数 #
bash
# 修改参数
varnishadm param.set thread_pool_max 1000
# 修改超时
varnishadm param.set connect_timeout 5
9.3 常用参数 #
| 参数 | 默认值 | 说明 |
|---|---|---|
| default_ttl | 120 | 默认缓存时间 |
| default_grace | 10 | 默认宽限时间 |
| default_keep | 0 | 默认保持时间 |
| max_restarts | 4 | 最大重启次数 |
| max_retries | 4 | 最大重试次数 |
| send_timeout | 600 | 发送超时 |
| idle_send_timeout | 60 | 空闲发送超时 |
十、完整配置示例 #
10.1 基础配置 #
vcl
vcl 4.1;
import std;
# 后端定义
backend default {
.host = "127.0.0.1";
.port = "8080";
.connect_timeout = 5s;
.first_byte_timeout = 90s;
.between_bytes_timeout = 2s;
.max_connections = 300;
}
# ACL定义
acl purge {
"localhost";
"192.168.1.0"/24;
}
# 初始化
sub vcl_init {
# VMOD初始化
}
# 请求处理
sub vcl_recv {
# PURGE请求处理
if (req.method == "PURGE") {
if (!client.ip ~ purge) {
return (synth(405, "Not allowed."));
}
return (purge);
}
# BAN请求处理
if (req.method == "BAN") {
if (!client.ip ~ purge) {
return (synth(405, "Not allowed."));
}
ban("req.url ~ " + req.url);
return (synth(200, "Banned."));
}
# 非GET/HEAD请求
if (req.method != "GET" && req.method != "HEAD") {
return (pass);
}
# 移除静态资源的Cookie
if (req.url ~ "\.(css|js|png|gif|jpg|jpeg|ico|svg|woff|woff2)$") {
unset req.http.Cookie;
return (hash);
}
# 健康检查
if (req.url == "/healthcheck") {
return (synth(200, "OK"));
}
return (hash);
}
# 缓存键计算
sub vcl_hash {
hash_data(req.url);
if (req.http.Host) {
hash_data(req.http.Host);
}
return (lookup);
}
# 缓存命中
sub vcl_hit {
return (deliver);
}
# 缓存未命中
sub vcl_miss {
return (fetch);
}
# 后端响应处理
sub vcl_backend_response {
# 设置默认TTL
if (beresp.ttl <= 0s) {
set beresp.ttl = 5m;
}
# 静态资源长缓存
if (bereq.url ~ "\.(css|js|png|gif|jpg|jpeg|ico|svg|woff|woff2)$") {
set beresp.ttl = 1d;
unset beresp.http.Set-Cookie;
}
# 不缓存带Set-Cookie的响应
if (beresp.http.Set-Cookie) {
set beresp.uncacheable = true;
set beresp.ttl = 0s;
}
# 设置宽限时间
set beresp.grace = 1h;
}
# 响应处理
sub vcl_deliver {
# 添加缓存状态头
if (obj.hits > 0) {
set resp.http.X-Cache = "HIT";
set resp.http.X-Cache-Hits = obj.hits;
} else {
set resp.http.X-Cache = "MISS";
}
# 移除敏感头
unset resp.http.X-Powered-By;
unset resp.http.Via;
}
# 合成响应
sub vcl_synth {
set resp.http.Content-Type = "text/html; charset=utf-8";
synthetic({"<!DOCTYPE html>
<html>
<head><title>"} + resp.status + " " + resp.reason + {"</title></head>
<body>
<h1>"} + resp.status + " " + resp.reason + {"</h1>
<p>"} + resp.reason + {"</p>
</body>
</html>
"});
return (deliver);
}
十一、配置管理 #
11.1 加载新配置 #
bash
# 加载新VCL
varnishadm vcl.load new_config /etc/varnish/default.vcl
# 使用新VCL
varnishadm vcl.use new_config
# 查看VCL列表
varnishadm vcl.list
11.2 热重载 #
bash
# 使用varnishreload脚本
varnishreload
# 或手动操作
varnishadm vcl.load reload_$(date +%s) /etc/varnish/default.vcl
varnishadm vcl.use reload_$(date +%s)
11.3 配置回滚 #
bash
# 查看VCL列表
varnishadm vcl.list
# 回滚到旧配置
varnishadm vcl.use old_config_name
# 删除VCL
varnishadm vcl.discard unused_config
十二、总结 #
本章我们学习了:
- 配置文件结构:default.vcl、secret、varnish.params
- VCL语法基础:版本声明、注释、数据类型、运算符
- 后端配置:单后端、多后端、参数详解
- ACL配置:访问控制列表定义和使用
- 子程序详解:各子程序的用途和返回值
- 内置变量:请求、响应、对象等变量
- 启动参数:存储、线程、内存、超时配置
- 配置管理:加载、重载、回滚操作
掌握配置基础后,让我们进入下一章,学习Varnish的基本命令!
最后更新:2026-03-28