用于按需域/多租户的 Varnish 缓存
Varnish caching for on demand domains / Multitenancy
我一直在尝试使用 Caddy 和清漆设置自定义 CDN。这个想法是按需生成 SSL 证书,然后将其传递给清漆,清漆进一步将其发送到作为 nodejs 应用程序的后端服务器。如果请求匹配,则清漆 returns 缓存结果,否则获取新数据。
图中描述了工作
flow diagram
以下是相应的文件:
docker-compose.yml
version: '3.7'
networks:
web:
external: true
internal:
external: false
driver: bridge
services:
caddy:
image: caddy
container_name: caddy
restart: unless-stopped
ports:
- "8080:8080"
- "80:80"
- "443:443"
volumes:
- $PWD/Caddyfile:/etc/caddy/Caddyfile
- $PWD/site:/srv
- caddy_data:/data
- caddy_config:/config
networks:
- web
varnish:
container_name: varnish
image: varnish:stable
restart: unless-stopped
volumes:
- $PWD/data/varnish/default.vcl:/etc/varnish/default.vcl
networks:
- web
- internal
volumes:
caddy_data:
external: true
caddy_config:
Caddyfile
{
on_demand_tls {
ask https://check-domain-URL
}
}
https:// {
tls {
on_demand
}
reverse_proxy varnish:80 {
header_up Host {host} # Won't work with another value or transparent preset
header_up X-Forwarded-Host {host}
header_up X-Real-IP {remote}
header_up X-Forwarded-For {remote}
header_up X-Forwarded-Proto {scheme}
header_up X-Caddy-Forwarded 1
header_down Cache-Control "public, max-age=31536000"
}
header /_next/static/* {
Cache-Control "public, max-age=31536000, immutable"
}
}
:8080 {
reverse_proxy backend-address:3000
}
default.vcl
vcl 4.0;
backend default {
.host = "caddy";
.port = "8080";
}
sub vcl_deliver
{
# Insert Diagnostic header to show Hit or Miss
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";
}
}
sub vcl_backend_response {
set beresp.ttl = 10s;
set beresp.grace = 1h;
}
一切正常
- 正在生成 SSL 证书
- 代理正在运行
- Varnish 正在返回结果
- 代理正在获取后端
唯一的问题是 Varnish Cache 总是 miss
,这是它应该做的一件事
我已经尝试了所有方法,但看起来清漆将每个请求都视为新请求。
有什么想法吗?
为了理解您收到缓存未命中的原因,您需要了解 built-in VCL。
这是在后台执行的VCL代码。请查看以下解释此内容的教程:https://www.varnish-software.com/developers/tutorials/varnish-builtin-vcl/.
Built-in VCL缓存绕过总结
我总结一下Varnish不缓存的标准情况:
- 当请求方法不是
GET
或HEAD
时
- 当请求包含
Authorization
header
- 当请求包含
Cookie
header
- 当响应包含
Set-Cookie
header
- 由于
Expires
header或max-age=0
或s-maxage=0
在Cache-Control
header[=中响应TTL为零时58=]
- 当响应在
Cache-Control
header 中包含 private
、no-cache
或 no-store
- 当有
Vary: *
响应时 header
正在使用 varnishlog
检查缓存 miss/bypass
找出缓存未命中原因或绕过缓存原因的一种简单方法是使用 varnishlog
.
您可以运行以下命令来检查主页的日志:
sudo varnishlog -g request -q "ReqUrl eq '/'"
Please change /
into the desire URL.
写VCL来补偿
如果您的应用程序不符合 built-in VCL 规范,您将不得不编写一些 VCL 代码来弥补这一点。
在大多数情况下,它会剥离跟踪 cookie 或定义哪些 URL 模式应绕过缓存,同时强制在所有其他页面上进行缓存查找。
Have a look at the logs to figure out what's what and if you need help, just add a log transaction to your question and I'll help you out.
我一直在尝试使用 Caddy 和清漆设置自定义 CDN。这个想法是按需生成 SSL 证书,然后将其传递给清漆,清漆进一步将其发送到作为 nodejs 应用程序的后端服务器。如果请求匹配,则清漆 returns 缓存结果,否则获取新数据。 图中描述了工作 flow diagram
以下是相应的文件: docker-compose.yml
version: '3.7'
networks:
web:
external: true
internal:
external: false
driver: bridge
services:
caddy:
image: caddy
container_name: caddy
restart: unless-stopped
ports:
- "8080:8080"
- "80:80"
- "443:443"
volumes:
- $PWD/Caddyfile:/etc/caddy/Caddyfile
- $PWD/site:/srv
- caddy_data:/data
- caddy_config:/config
networks:
- web
varnish:
container_name: varnish
image: varnish:stable
restart: unless-stopped
volumes:
- $PWD/data/varnish/default.vcl:/etc/varnish/default.vcl
networks:
- web
- internal
volumes:
caddy_data:
external: true
caddy_config:
Caddyfile
{
on_demand_tls {
ask https://check-domain-URL
}
}
https:// {
tls {
on_demand
}
reverse_proxy varnish:80 {
header_up Host {host} # Won't work with another value or transparent preset
header_up X-Forwarded-Host {host}
header_up X-Real-IP {remote}
header_up X-Forwarded-For {remote}
header_up X-Forwarded-Proto {scheme}
header_up X-Caddy-Forwarded 1
header_down Cache-Control "public, max-age=31536000"
}
header /_next/static/* {
Cache-Control "public, max-age=31536000, immutable"
}
}
:8080 {
reverse_proxy backend-address:3000
}
default.vcl
vcl 4.0;
backend default {
.host = "caddy";
.port = "8080";
}
sub vcl_deliver
{
# Insert Diagnostic header to show Hit or Miss
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";
}
}
sub vcl_backend_response {
set beresp.ttl = 10s;
set beresp.grace = 1h;
}
一切正常
- 正在生成 SSL 证书
- 代理正在运行
- Varnish 正在返回结果
- 代理正在获取后端
唯一的问题是 Varnish Cache 总是 miss
,这是它应该做的一件事
我已经尝试了所有方法,但看起来清漆将每个请求都视为新请求。
有什么想法吗?
为了理解您收到缓存未命中的原因,您需要了解 built-in VCL。
这是在后台执行的VCL代码。请查看以下解释此内容的教程:https://www.varnish-software.com/developers/tutorials/varnish-builtin-vcl/.
Built-in VCL缓存绕过总结
我总结一下Varnish不缓存的标准情况:
- 当请求方法不是
GET
或HEAD
时
- 当请求包含
Authorization
header - 当请求包含
Cookie
header - 当响应包含
Set-Cookie
header - 由于
Expires
header或max-age=0
或s-maxage=0
在Cache-Control
header[=中响应TTL为零时58=] - 当响应在
Cache-Control
header 中包含 - 当有
Vary: *
响应时 header
private
、no-cache
或 no-store
正在使用 varnishlog
检查缓存 miss/bypass找出缓存未命中原因或绕过缓存原因的一种简单方法是使用 varnishlog
.
您可以运行以下命令来检查主页的日志:
sudo varnishlog -g request -q "ReqUrl eq '/'"
Please change
/
into the desire URL.
写VCL来补偿
如果您的应用程序不符合 built-in VCL 规范,您将不得不编写一些 VCL 代码来弥补这一点。
在大多数情况下,它会剥离跟踪 cookie 或定义哪些 URL 模式应绕过缓存,同时强制在所有其他页面上进行缓存查找。
Have a look at the logs to figure out what's what and if you need help, just add a log transaction to your question and I'll help you out.