Akemi

Varnish缓存加速

2025/04/10

Varnish 是一款高性能的 HTTP 加速器(HTTP Accelerator),专为提升 Web 应用的速度和可扩展性而设计。它本质上是一个 反向代理缓存服务器,通过缓存静态和动态内容,大幅减少后端服务器(如 Apache、Nginx)的负载,提升用户访问速度。

安装varnish

1
2
3
4
5
6
7

hostnamectl set-hostname varnish && bash

yum -y install varnish
yum -y install varnish-docs # 文档
systemctl enable varnish --now
systemctl enable varnishncsa.service --now # 启动日志进程

测试日志

1
2
3
4
5
curl localhost:80

tail -f /var/log/varnish/varnishncsa.log
::1 - - [10/Apr/2025:18:22:10 +0800] "GET http://localhost/ HTTP/1.1" 503 278 "-" "curl/7.76.1"

varnishd命令行配置

varnish有两个可配置的方式

  • varnishd命令行配置工具
  • /etc/varnish/default.vcl配置文件

varnishd配置参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
varnishd是一个守护进程

查看varnish的service文件就可以看出来
cat /usr/lib/systemd/system/varnish.service

...
ExecStart=/usr/sbin/varnishd -a :6081 -f /etc/varnish/default.vcl -s malloc,256m
ExecReload=/usr/sbin/varnishreload
...

可以看到启动命令是
varnishd -a :6081 -f /etc/varnish/default.vcl -s malloc,256m

varnishd -h查看帮助
参数 说明 示例
-a 指定监听地址和端口(客户端访问入口),支持多协议(HTTP/HTTPS)。 -a :80(监听所有 IP 的 80 端口)
-a 192.168.1.10:8080,PROXY(启用 PROXY 协议支持)
-T 指定管理接口(CLI)地址和端口,用于动态配置和监控。 -T 127.0.0.1:6082(本地管理端口)
-f 指定 VCL 配置文件路径,Varnish 启动时加载该配置。 -f /etc/varnish/default.vcl
-s 定义缓存存储后端(存储类型和大小),支持多种存储引擎。 -s malloc,1G(内存分配 1GB)
-s file,/var/lib/varnish/storage.bin,10G(文件存储)
-n 指定工作目录(日志、PID 文件存放路径)。 -n /var/lib/varnish

修改varnishd配置

正常服务器端口都是80对吧,也就是外部通过http或https访问它所认为的web后端时,会使用80或443端口,但varnishd默认使用的是6082端口,这怎么办呢?

创建一个/etc/system/varnish.service.d/httpport.conf:

子配置文件(drop-in 文件)可以覆盖父 Service 配置文件(主单元文件)中的相同字段。这是 systemd 设计中的一个核心特性,允许用户在不直接修改原始服务文件的情况下,通过添加或覆盖特定配置项来自定义服务行为。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
mkdir /etc/systemd/system/varnish.service.d
cat > /etc/systemd/system/varnish.service.d/httpport.conf <<EOF
[Service]
ExecStart=
ExecStart=/usr/sbin/varnishd -a :80 -f /etc/varnish/default.vcl -s malloc,256m
EOF

systemctl daemon-reload
systemctl restart varnish
firewall-cmd --add-service=http
firewall-cmd --add-service=http --permanent
setenforce 0

netstat -tunlp | grep var | grep tcp6 -v
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 4950/varnishd
tcp 0 0 127.0.0.1:35427 0.0.0.0:* LISTEN 4950/varnishd

可以看到已经在监听80端口了

为什么不直接修改/usr/lib/systemd/system/varnish.service

因为如果varnishd更新了,那么这个service文件也会被覆盖掉

配置文件VCL

VCL(Varnish Configuration Language)是 Varnish HTTP 缓存服务器的核心配置语言,用于定义请求处理逻辑(如缓存规则、后端路由、流量过滤等)。它通过一系列“子例程”(Subroutines)控制 Varnish 对 HTTP 请求和响应的处理流程,支持高度灵活的缓存策略定制。

VCL 代码在加载时会被 编译为 C 语言代码,再编译成动态库供 Varnish 使用,因此性能极高。

VCL阶段

VCL 通过预定义的子例程定义处理流程,每个子例程在不同阶段触发:

子例程 触发时机 典型用途
vcl_recv 客户端请求到达时 决定是否缓存、修改请求头、选择后端服务器
vcl_backend_fetch 向后端服务器发起请求前 修改向后端发送的请求(如添加认证头)
vcl_backend_response 收到后端响应后 控制缓存策略(如缓存时间、缓存键)、修改响应头
vcl_deliver 将响应返回给客户端前 添加调试头(如 X-Cache: HIT/MISS)、记录日志
vcl_hash 生成缓存键时 自定义缓存键(如包含用户 Cookie)
vcl_hit/vcl_miss 缓存命中或未命中时 特殊处理(如命中后刷新缓存)

允许刷新缓存

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# acl允许ip列表
acl purge_allow_list {
"localhost";
"10.163.2.200";
}

sub vcl_recv {
# 允许 PURGE 方法清除缓存
if (req.method == "PURGE") {
# 仅允许特定 IP 执行 PURGE 操作
if (client.ip !~ purge_allow_list) {
return (synth(405, "Not Allowed"));
}
# 执行缓存清除
return (purge);
}
}

缓存静态文件,并绕过动态缓存

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
sub vcl_recv {
# 匹配静态资源请求(图片、CSS、JS)
if (req.url ~ "\.(jpg|jpeg|png|gif|css|js|webp)$") {
# 删除请求中的 Cookie,避免 Cookie 影响缓存命中率
unset req.http.Cookie;
# 强制进入缓存流程(生成缓存键)
return (hash);
}
# 如果请求方法是 GET 或 HEAD,则继续处理
if (req.method == "GET" || req.method == "HEAD") {
return (hash);
}

# 匹配 API 或动态路径
if (req.url ~ "^/api/" || req.url ~ "^/dynamic/") {
# 绕过缓存,直接向后端请求
return (pass);
}
# 其他请求(如 POST)直接绕过缓存
return (pass);
}

后端配置

后端服务器的ip配置略过

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
# varnish主机
只下载rpm包
yum -y --downloadonly --downloaddir=/root/httpd install httpd
ls httpd/
apr-1.7.0-12.el9.x86_64.rpm httpd-core-2.4.62-4.el9.x86_64.rpm
apr-util-1.6.1-23.el9.x86_64.rpm httpd-filesystem-2.4.62-4.el9.noarch.rpm
apr-util-bdb-1.6.1-23.el9.x86_64.rpm httpd-tools-2.4.62-4.el9.x86_64.rpm
apr-util-openssl-1.6.1-23.el9.x86_64.rpm mailcap-2.1.49-5.el9.noarch.rpm
centos-logos-httpd-90.8-2.el9.noarch.rpm mod_http2-2.0.26-4.el9.x86_64.rpm
httpd-2.4.62-4.el9.x86_64.rpm mod_lua-2.4.62-4.el9.x86_64.rpm

scp -r httpd 1.1.1.1:~
scp -r httpd 1.1.1.2:~
scp -r httpd 1.1.1.3:~
ssh 1.1.1.1 "rpm -vih httpd/*"
ssh 1.1.1.2 "rpm -vih httpd/*"
ssh 1.1.1.3 "rpm -vih httpd/*"

ssh 1.1.1.1 "echo 'wangsheng-1' > /var/www/html/index.html && sed -i 's/^Listen.*/Listen 8080/g' /etc/httpd/conf/httpd.conf && systemctl enable httpd --now"
ssh 1.1.1.2 "echo 'wangsheng-2' > /var/www/html/index.html && sed -i 's/^Listen.*/Listen 8080/g' /etc/httpd/conf/httpd.conf && systemctl enable httpd --now"
ssh 1.1.1.3 "echo 'wangsheng-3' > /var/www/html/index.html && sed -i 's/^Listen.*/Listen 8080/g' /etc/httpd/conf/httpd.conf && systemctl enable httpd --now"
ssh 1.1.1.1 "systemctl restart httpd && systemctl disable firewalld --now"
ssh 1.1.1.2 "systemctl restart httpd && systemctl disable firewalld --now"
ssh 1.1.1.3 "systemctl restart httpd && systemctl disable firewalld --now"

# varnish配置访问后端8080端口
vim /etc/varnish/default.vcl
backend default {
.host = "1.1.1.1";
.port = "8080";
}
systemctl restart varnish

curl 1.1.1.1:8080
curl localhost
wangsheng
可见已经将本地80端口的流量代理到了后端的8080端口

curl localhost
curl localhost
curl localhost
curl localhost
curl localhost
curl localhost

后续的访问都已经被缓存了
默认情况下: Varnish 缓存命中时,后端服务器不会记录请求日志。
cat /var/log/varnish/varnishncsa.log
::1 - - [10/Apr/2025:20:28:18 +0800] "GET http://localhost/ HTTP/1.1" 200 10 "-" "curl/7.76.1"
::1 - - [10/Apr/2025:20:28:24 +0800] "GET http://localhost/ HTTP/1.1" 200 10 "-" "curl/7.76.1"
192.168.10.254 - - [10/Apr/2025:20:31:13 +0800] "GET http://10.163.2.100/ HTTP/1.1" 200 10 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.0.0 Safari/537.36 Edg/133.0.0.0"
192.168.10.254 - - [10/Apr/2025:20:31:13 +0800] "GET http://10.163.2.100/favicon.ico HTTP/1.1" 404 196 "http://10.163.2.100/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.0.0 Safari/537.36 Edg/133.0.0.0"
192.168.10.254 - - [10/Apr/2025:20:31:16 +0800] "GET http://10.163.2.100/ HTTP/1.1" 304 0 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.0.0 Safari/537.36 Edg/133.0.0.0"

# 清除缓存
varnishadm 'ban req.url == /index.html'
# 清除全部
varnishadm 'ban req.url ~ .*'
CATALOG
  1. 1. 安装varnish
    1. 1.1. 测试日志
  2. 2. varnishd命令行配置
    1. 2.1. varnishd配置参数
      1. 2.1.1. 修改varnishd配置
    2. 2.2. 配置文件VCL
      1. 2.2.1. VCL阶段
      2. 2.2.2. 允许刷新缓存
      3. 2.2.3. 缓存静态文件,并绕过动态缓存
  3. 3. 后端配置