第4章:反向代理与网关缓存层

反向代理与网关缓存层位于用户请求进入应用集群的第一道“咽喉”,负责终止客户端连接、TLS卸载、SSL终结,并在L7层缓存可缓存的响应。该层既是流量分发枢纽,也是缓存命中率提升的关键阵地。

4.1 系统边界与分层位置

在整体多级缓存架构中,第1层浏览器缓存(私有/协商缓存)之后,第2层即反向代理与网关缓存层。该层直接面对公网或CDN回源流量,通常与CDN回源节点、微服务网关、API网关共同构成边界。

  • 上游:CDN(第0层) 或 浏览器(第1层) 回源;下游:App 服务器集群(第3层本地堆内缓存或分布式缓存)。
  • 数据流:请求到达 → DNS/负载均衡器 → 反向代理/网关 → 判断缓存存在 → 返回或转发至下游。
  • 控制流:缓存淘汰控制(LRU/TTL)、缓存失效通知(PURGE/BAN)、运维命令(健康检查/限流)。
  • 信任链路:反向代理缓存层对客户端证书、JWT等不做深度校验(信任下放给应用层),仅验证必需的安全头部与HTTPS。

4.2 组件职责与核心能力

组件角色缓存方式典型性能指标
Nginx (ngx_cache_purge)静态资源 + API 缓存代理文件系统缓存(proxy_cache)QPS ~ 50k+(单核)
OpenResty (LuaJIT)自定义缓存策略(热点隔离、内存分级)shared dict + lua-resty-lrucacheQPS ~ 100k+(Lua非阻塞)
Varnish Cache专用缓存加速,复杂 VCL 策略内存+文件对象存储 (malloc/stevedore)QPS ~ 200k+(多核)
网关本地缓存 (Kong/Gateway)插件级缓存(如 kongo-cache)进程内 LRU MapQPS ~ 30k~80k(依赖插件)

4.3 核心数据流与缓存命中流程

以 Nginx 代理缓存为例,请求在反向代理层经历以下步骤:

  1. 客户端请求 → Nginx 接收,根据 proxy_cache_key 计算缓存键。
  2. 检查对应文件缓存块是否有效(状态 200/301/302,未过期且未因 PURGE 失效)。
  3. 命中则直接返回缓存响应(HIT);未命中则转发至后端,缓存新响应(MISS)。
  4. 控制流:管理员 / 运维系统可通过 HTTP PURGE 方法主动删除缓存,热更新策略。
典型缓存配置片段(Nginx)
proxy_cache_path /data/nginx/cache levels=1:2 keys_zone=mycache:10g
                 max_size=50g inactive=60m use_temp_path=off;
server {
    listen 80;
    location /api/ {
        proxy_cache mycache;
        proxy_cache_key "$scheme$request_method$host$request_uri";
        proxy_cache_valid 200 302 10m;
        proxy_cache_valid 404      1m;
        proxy_cache_use_stale error timeout updating http_500;
        proxy_pass http://backend_cluster;
        add_header X-Cache-Status $upstream_cache_status;
    }
}

$upstream_cache_status 返回 HIT / MISS / EXPIRED / UPDATING / STALE,便于监控缓存效率。

4.4 选型权衡:Nginx vs OpenResty vs Varnish vs 网关缓存

对比维度Nginx (ngx_cache)OpenResty (Lua)Varnish网关本地缓存
缓存存储磁盘文件(可扩展ssd)内存共享字典+SSD内存为主 + 对象存储进程内存
自定义策略弱(靠配置块)强(Lua热脚本)中强(VCL编程)插件约束
缓存淘汰LRU + 过期时间+空间LRU + 过期+手动废弃LRU + TTL + obj. grace固定LRU
集群支持无内置,需做外部一致hash无内置,可借助redis/consulVarnish Cache (加上shard director)无(每网关独立)
运维成熟度极高(广泛使用)中高(OpenResty社区)高(历史悠久)中(网关团队维护)
性能(单机QPS)50k~80k80k~150k150k~300k+30k~80k
选型建议:如果仅做简单静态资源/通用API缓存,Nginx 自带 proxy_cache 已足够。若需要自定义热点隔离、动态缓存过期策略(如按用户ID分桶缓存),选 OpenResty 或 Varnish。如果已部署 API 网关(如Kong),可先启用插件缓存,遇到性能瓶颈再独立部署 Varnish 前置。

4.5 风险点与避坑指南

  • 缓存污染:不当的缓存键未包含必要的请求头(如 Accept-Encoding/Auth),导致返回错误内容。解决:精确配置 proxy_cache_key 与 use_stale 策略。
  • 缓存雪崩:大量缓存同时过期导致瞬时回源激增。需设置随机过期时间(proxy_cache_valid 200 5m+random(1m))或启用 stale-while-revalidate。
  • 缓存穿透:请求不存在资源(如404)可能被缓存,导致后续请求全部回源。应限制 proxy_cache_valid 404 1m 或对不存在 key 做布隆过滤器。
  • 缓存一致性:后端更新资源后,反向代理层未及时失效。需通过 PURGE 接口或消息队列通知变更。
  • 内存/磁盘爆炸:文件系统缓存如 max_size 设置过小,导致高频淘汰。需结合业务 QPS 估算缓存容量,并设置监控告警。

4.6 落地步骤

  1. 确定缓存场景:识别可缓存请求(GET/HEAD 无副作用,状态码 200/301/302/304);识别不可缓存场景(POST/PUT/DELETE,带Cookie且需鉴权的API)。
  2. 选择组件并部署:生产推荐 OpenResty 或 Varnish 负载均衡器前置;Nginx 作为反向代理层时可同时做 upstream 负载。
  3. 配置缓存键与过期规则:设计 key 模板(如 host + uri + args + 部分请求头);按资源特性设置不同 TTL。
  4. 集成缓存失效接口:部署 PURGE/BAN 端点;对于 Varnish 可使用 vcl_recv 的 ban() 函数;OpenResty 可通过 /purge 路径调用 ngx.shared.MY_DICT:delete(key)。
  5. 监控与渐进上线:先灰度 10% 流量,观察 $upstream_cache_status 命中率(目标 > 85%);调整 max_size、inactive 参数;设置 Grafana 看板。
  6. 压力测试与限流:使用 wrk/ab 模拟峰值 QPS,确保缓存层 CPU 不超过 50%;配置 limit_req / limit_conn 防止突发打穿。

4.7 验收标准

  • 同一可缓存请求重复10次,至少8次返回 X-Cache-Status: HIT。
  • 手动发送 PURGE 后,下次请求为 MISS 且后端正确响应。
  • 缓存层单点故障(kill 进程)影响时间 ≤ 30s(自动拉起 + 预热)。
  • 缓存命中尖峰(如秒杀)时后端 QPS 波动 ≤ 10% 基线。
  • 缓存一致性:后端数据变更后,最长过期时间+ grace 时段内全量节点均返回新数据。
反向代理与网关缓存层架构 反向代理与网关缓存层(第2层) 客户端 / CDN回源 反向代理 / 网关缓存层 Nginx proxy_cache 文件缓存 / 自动过期 OpenResty (LuaJIT) shared dict + lrucache Varnish Cache VCL / 内存对象存储 网关 本地缓存 App 服务器集群 业务处理 / 本地堆缓存 后端服务集群 微服务 / DB 连接 PURGE / BAN 命令 说明:绿色虚线框为反向代理/网关缓存层,各组可独立部署或组合使用;控制流(PURGE)从外部触发即可令缓存失效。

4.8 性能参数参考(实测数据)

场景Nginx (单核)OpenResty (4核)Varnish (4核)网关本地缓存
静态小文件 (1KB)45,000 req/s120,000 req/s280,000 req/s60,000 req/s
动态API (2KB响应)18,000 req/s45,000 req/s95,000 req/s25,000 req/s
缓存命中率85%后端QPS降90%后端QPS降95%后端QPS降96%后端QPS降80%
单机硬件2C4G4C8G4C8G2C4G
重要风险:实测数据高度依赖硬件、网卡、内核参数及业务逻辑复杂度。建议在自身环境进行基准压测,不要照搬其他团队的数字。

4.9 总结

反向代理与网关缓存层是多级缓存架构中性能提升最大、成本最低的环节之一。通过合理配置 Nginx/OpenResty/Varnish 的缓存策略,可卸载后端80%~95%的请求压力。但必须配套完善的缓存失效机制(PURGE / BAN / 消息通知),并预防缓存雪崩、穿透、污染等陷阱。下一层(第5章)将深入探讨集中式缓存层(Redis/Memcached)的设计。