如何用Varnish缓存内容并实现无缓存HTTPS反向代理?
使用Varnish实现游戏文件缓存+无缓存HTTPS反向代理方案
架构说明
Varnish原生不处理HTTPS请求,因此需要前置SSL终止层(这里用你熟悉的Nginx),整体流程:
客户端HTTPS请求 → Nginx(SSL终止) → Varnish(缓存/路由) → 目标后端服务器
1. Nginx SSL终止配置
先配置Nginx监听443端口,完成SSL解密后转发请求到Varnish(示例端口8080),确保传递正确的Host头:
server { listen 443 ssl; server_name game-update.example.com no-cache.example.com; # SSL证书配置(替换为你的证书路径) ssl_certificate /path/to/fullchain.pem; ssl_certificate_key /path/to/privkey.pem; # 转发请求到Varnish location / { proxy_pass http://127.0.0.1:8080; 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 $scheme; } }
2. Varnish核心VCL配置
编辑/etc/varnish/default.vcl,区分缓存/无缓存请求,配置后端路由和缓存策略:
定义后端服务器
# 游戏更新文件后端(缓存目标) backend game_update { .host = "game-update-backend.example.com"; .port = "80"; # 如果后端是HTTPS,添加以下配置: # .ssl = true; # .ssl_verify_hostname = false; # 自签名证书需开启,信任证书则设为true } # 无缓存服务后端 backend no_cache_service { .host = "no-cache-backend.example.com"; .port = "80"; }
请求处理逻辑(vcl_recv)
sub vcl_recv { # 标记HTTPS请求来源 if (req.http.X-Forwarded-Proto) { set req.http.X-Forwarded-Proto = "https"; } # 规则1:缓存游戏更新/文件类请求 if (req.host == "game-update.example.com" || req.url ~ "^/update/|\.(zip|exe|pak|bin)$") { # 仅缓存GET/HEAD请求 if (req.method != "GET" && req.method != "HEAD") { return (pass); } # 清除Cookie避免缓存碎片化(游戏更新通常无需Cookie) unset req.http.Cookie; # 自定义缓存键,确保不同域名的资源独立缓存 set req.hash_data = req.host; set req.hash_data = req.url; # 强制设置缓存有效期(1天,按需调整) set req.http.Cache-Control = "public, max-age=86400"; return (hash); } # 规则2:无缓存反向代理请求 if (req.host == "no-cache.example.com") { set req.backend_hint = no_cache_service; return (pass); # 直接转发到后端,不经过缓存 } # 默认规则:其他请求直接转发 return (pass); }
响应处理逻辑(vcl_backend_response)
sub vcl_backend_response { # 游戏更新资源:强制缓存并清除后端Set-Cookie if (bereq.host == "game-update.example.com" || bereq.url ~ "^/update/|\.(zip|exe|pak|bin)$") { unset beresp.http.Set-Cookie; set beresp.ttl = 86400s; set beresp.http.Cache-Control = "public, max-age=86400"; set beresp.http.X-Cached-By = "Varnish"; return (deliver); } # 无缓存资源:禁用缓存 if (bereq.host == "no-cache.example.com") { set beresp.ttl = 0s; set beresp.http.Cache-Control = "no-cache, no-store, must-revalidate"; return (deliver); } }
3. dnsmasq域名解析配置
将需要代理的域名指向Nginx服务器IP,编辑/etc/dnsmasq.conf添加:
# 游戏更新域名解析到Nginx IP address=/game-update.example.com/192.168.1.100 # 无缓存服务域名解析到Nginx IP address=/no-cache.example.com/192.168.1.100
重启dnsmasq生效:
systemctl restart dnsmasq
排查Host头代理失败问题
- Nginx必须传递Host头:确保
proxy_set_header Host $host;存在,否则Varnish拿到的Host是127.0.0.1:8080,无法匹配后端规则。 - 检查Varnish日志:用
varnishlog -g request查看请求流程,确认Host头是否正确传递,规则是否匹配。 - 后端HTTPS适配:如果后端是HTTPS,必须在Varnish backend配置中开启
.ssl = true,并根据证书情况设置.ssl_verify_hostname。
内容的提问来源于stack exchange,提问作者Mahdi
相关产品推荐
相关产品推荐

