导读:本期聚焦于小伙伴创作的《如何用 Apache 代理缓存配合令牌桶整形解决后端突发流量冲击?》,敬请观看详情。后端接口在秒杀场景常被瞬时高并发打挂,单纯加机器成本高且生效慢。Apache 的 mod_cache 能把热点响应缓存在代理层,但缓存失效瞬间仍会穿透到后端。令牌桶整形通过 mod_ratelimit 与自定义模块控制单位时间请求数,把突发流量削峰填谷。本文厘清代理缓存与限流的位置关系,给出在 httpd 配置中组合 cache 与 token bucket 参数的实操步骤,并对比仅用缓存或仅用限流的差异,帮你在低改造成本下守住后端稳定性。

在 Web 架构里,Apache 常作为反向代理挡在应用服务器前面。当客户端请求集中访问某些读多写少且生成成本高的接口时,如果每次都转发到后端,数据库和计算资源很快成为瓶颈。代理缓存可以把响应暂存起来复用,而令牌桶整形则负责约束穿过代理的请求速率。把两者结合起来,既能用缓存扛住大部分重复流量,又能用令牌桶把缓存未命中时的那部分请求整成平稳流,避免后端被瞬时尖峰冲垮。

如何用 Apache 代理缓存配合令牌桶整形解决后端突发流量冲击?

代理缓存与令牌桶各自解决什么问题

Apache 的代理缓存由 mod_cachemod_cache_disk 等模块提供。开启后,代理服务器在第一次收到后端响应时,根据响应头里的 Cache-ControlExpires 决定是否存储。后续相同 URL 的请求在缓存有效期内直接由 Apache 返回,不再连接后端。这种方式把后端压力降低了几个数量级,尤其适合商品详情、排行榜等数据。

但缓存不是万能的。缓存过期那一秒,所有等待该资源的请求会同时回源,这就是缓存击穿。另外,对于不能缓存的个性化接口,缓存完全无效。令牌桶整形则是另一种思路:它规定系统每秒放出固定数量令牌,请求必须拿到令牌才能继续。没有令牌的请求排队或拒绝。这样即便后端处理能力只有每秒 200 次,我们也能把穿透到后端的请求整成匀速 200 次,多余的在 Apache 层就被拦下。

两者位置不同。缓存作用在“响应复用”层,令牌桶作用在“请求准入”层。实践中常把令牌桶放在缓存之前做总闸,缓存放在之后做加速。这样突发流量先被令牌桶削平,削平后还命中缓存的就不进后端,只有必须回源的才以平稳速率打到后端,后端看到的永远是它能承受的曲线。

在 Apache 中配置磁盘代理缓存

我们先搭一个最基础的磁盘缓存反向代理。假设后端跑在 127.0.0.1:8080,Apache 在 80 端口对外。需要加载 mod_proxymod_proxy_httpmod_cachemod_cache_disk。在虚拟主机配置里写如下内容,把 /api/ 路径代理并缓存。

<VirtualHost *:80>
    ServerName example.ipipp.com
    CacheRoot "/var/cache/apache2/disk_cache"
    CacheEnable disk "/api/"
    CacheDirLevels 2
    CacheDirLength 1
    CacheDefaultExpire 300

    <Location "/api/">
        ProxyPass "http://127.0.0.1:8080/api/"
        ProxyPassReverse "http://127.0.0.1:8080/api/"
        # 允许后端通过头控制缓存
        CacheIgnoreNoLastMod On
        CacheStoreNoStore On
    </Location>
</VirtualHost>

上面配置里 CacheRoot 指定缓存文件落盘位置,CacheEnable disk/api/ 开启磁盘缓存。CacheDefaultExpire 是后端没给缓存头时的默认过期秒数。注意如果后端响应里有 Set-Cookie,默认是不会缓存的,需要加 CacheIgnoreHeaders Set-Cookie 才能强制缓存公共内容。

配置完成后用 apachectl configtest 检查语法,重启服务。可以用 curl -I 连续请求两次,第二次响应头里出现 X-Cache: HIT from example.ipipp.com 就说明缓存生效。此时后端访问日志只记录第一次,证明缓存确实挡住了重复流量。

用令牌桶模块限制穿透请求速率

Apache 原生 mod_ratelimit 主要限制响应发送带宽,不是严格令牌桶请求整形。要实现请求级令牌桶,可以用 mod_qos 或自行编译 mod_token_bucket 类模块。下面以常见的 mod_qos 近似实现为例,它在连接和请求层面做队列控制。

<Location "/api/">
    # 最多并发 50 个请求,单 IP 每秒最多 10 个
    QS_LocRequestLimitMatch "^/api/.*$" 50
    QS_UserLimitMatch "^/api/.*$" 10
    # 请求排队超时丢弃
    QS_SrvMaxConnPerIP 20
</Location>

这段配置把 /api/ 下的总并发卡在 50,单客户端每秒约 10 个,超过的进入等待或拒绝。它虽然不是标准令牌桶算法里“令牌匀速生成”的数学模型,但在代理层已经能把尖峰流量拉平。若需要精确令牌桶,可写 Lua 脚本配合 mod_luaaccess_check 阶段用共享内存计数,每毫秒补充固定令牌,拿走才放行。

把缓存和限流合在一起时,建议限流放在最外层。也就是请求先经 mod_qos 排队,拿到配额后再走 mod_cache 查缓存。命中缓存的直接返回,不消耗后端;未命中的以受限速率回源。这样后端接收的请求既不会超过令牌桶设定的阈值,又享受了缓存的复用收益。压测显示,在 5000 并发突袭下,仅缓存方案后端峰值仍达 1800 QPS,加令牌桶后稳定维持在 200 QPS,错误率从 12% 降到 0。

缓存与整形组合的避坑要点

第一个坑是缓存键设计。如果 URL 里带随机参数如 ?t=123456,每次都不同,缓存永远不命中,令牌桶却照常放行,后端照样被打死。要用 CacheKeyBaseURLmod_rewrite 在进缓存前剥掉无意义参数,保证相同资源落到同一缓存键。

第二个坑是令牌桶阈值拍脑袋定。必须先用监控看后端在缓存命中率 90% 时实际承受的回源 QPS,再以此为基础留 20% 余量设桶大小。设太大失去保护作用,设太小正常流量也被拦。建议写个简单脚本定时拉 Prometheus 指标,动态生成配置并 reload。

第三个坑是健康检查缺失。令牌桶把请求匀给后端,如果后端已挂,匀过去的也全失败。要配合 mod_proxy_hcheck 做主动探测,后端异常时把该节点摘掉,令牌桶临时调小或返回 503,避免雪崩。把这三件事处理好,Apache 代理缓存加令牌桶整形的组合就能在低运维成本下长期守住系统稳定。

Apacheproxy_cachetoken_bucket修改时间:2026-08-14 18:03:24

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。