...

使用 Nginx 或 Apache 设置服务器端缓存 - 提高网站性能

我使用 Nginx阿帕奇 设置清除缓存规则,并监控对响应时间的影响。通过这种方式,我明显降低了服务器的负载,每秒可发送更多请求,并在高负载情况下保持动态网站的可靠快速运行。

中心点

在设置之前,我会明确组织目标:哪些内容可能会包含在 缓存多长时间和什么级别。对于动态页面,我规划了以下例外情况 会议 和个性化数据。我选择合适的架构,并检查反向代理是否合理。然后,我将配置结构化为简洁的 v 主机 并系统地检查标题。最后,我还进行锚定监控,以便可靠地评估每次更改的效果。

  • 建筑学 澄清
  • 缓存类型 定义
  • 页眉 引导
  • 无效 计划
  • 监测 建立

基础知识:服务器端缓存是什么意思?

服务器端缓存可保存对 要求 这样,我就可以在不重新计算的情况下提供经常请求的内容。由于应用程序、数据库和文件系统需要做的工作减少了,因此到第一个字节的时间明显缩短。我将缓存分为代理级缓存、FastCGI 缓存和静态文件的文件缓存。 资产.对于哪些内容被视为公开内容,哪些内容保持个性化,制定严格的计划非常重要。对于每条规则,我都会定义一个有效期(TTL),并明确清空缓存的条件。

Nginx 和 Apache - 架构和缓存概念

Nginx 工作 事件驱动 因此非常适合高并行性和快速缓存。Apache 使用进程和线程,但提供了非常灵活的模块环境,我可以对其进行精细控制。对于静态内容,Nginx 的 CPU 负载非常低,给人留下了深刻印象,而 Apache 在动态应用程序方面的功能深度则更胜一筹。如果使用反向代理,几乎所有应用程序都能从更短的响应时间中获益。我在这里概述了 Nginx 作为反向代理的性能: Nginx 作为反向代理.

下表总结了主要区别,并帮助我找到正确的 战略 来选择。这让我能够更好地对需求、工具和未来运营计划进行分类。我会考虑到维护、应用程序的复杂性和典型的负载高峰。内容越简单,激进的潜力就越大。 缓存.对于非常动态的内容,我倾向于使用特定的例外情况和较短的 TTL。

标准 阿帕奇 Nginx
软件架构 基于进程和线程 事件控制(异步)
静态内容 良好 非常快
动态内容 非常灵活(模块) 关于 PHP-FPM/Upstreams
缓存功能 mod_cache, mod_file_cache FastCGI 缓存、代理缓存
配置 通过 .htaccess 集中管理 集中在 nginx.conf 中

配置 Nginx:逐步配置 FastCGI 缓存

我首先定义了一个 缓存路径 和一个命名区域,这样 Nginx 就能以结构化的方式存储内容。然后,我连接 PHP 上游(如 PHP-FPM),并在适当位置激活 fastcgi_cache。对于动态应用程序,我会设置 缓存旁路 为 PHPSESSID 等 cookies 或登录用户使用,以便保持个性化页面的新鲜度。我使用 fastcgi_cache_valid 为状态代码分配 TTL,确保内容的时效性得到控制。通过 X-FastCGI-Cache 标头,我可以查看请求是命中、未命中还是通过,并据此完善规则。

配置 Apache:安全使用 mod_cache

在 Apache 下,我会激活 mod_cache 和 mod_cache_disk,或共享内存后端,具体取决于 目标.在 vHost 配置中,我特别开启了 CacheEnable,定义了 Expires 值,并忽略了 Set-Cookie 等标头(如果内容要保持公开)。为了进行更精细的控制,我使用了文件和路径作用域,这样只有合适的 资源 进入缓存。在应用程序允许的情况下,我会正确设置缓存控制,从而在应用程序和服务器之间建立清晰的交互。对于目录级别的规则,这个简洁的规则可以帮助我 .htaccess 指南.

缓存规则和边缘情况:cookie、会话、查询字符串

我阻止个性化 答案 例如使用会话 cookie。对于查询字符串,我会区分真正的变体(如分页)和跟踪参数,将其删除或忽略。对于 API 或搜索结果,我会分配较短的 TTL 或将其完全设置为 NO-CACHE,以避免误报。 点击数 要避免的。我不缓存文件下载和表单 POST,但可以积极缓存缩略图和资产。对于急于开展活动的登陆页面,我计划使用较短但有效的 TTL,并在进行更改时快速失效。

监控和调试:了解缓存命中率

我观察到 X-Cache 或 X-FastCGI-Cache 在 回复标题 并测量一段时间内的命中率。日志文件和状态模块会向我显示利用率、延迟和出错情况。通过更改后的短期测试运行,我可以检查未命中是否变成了命中,以及是否没有在 缓存 地。负载测试揭示了热点路径,有助于完善具体规则。这让我能够及早发现瓶颈,并在实际负载高峰时保持环境的响应速度。

缓存键设计和变化策略

一个干净的缓存键决定了不同的变体是被干净地分开还是无意中混在一起。我有意识地定义关键字,并将模式、主机、路径和相关参数考虑在内。我排除了跟踪参数,并纳入了真正的变体(如分页、排序、语言)。在 Nginx 层面,我通过变量和映射实现这一点;在 Apache,我通过特定规则并遵守 不同-标题:

  • 主机和协议分离: 如果同时存在 http/https 和 domain,则在密钥中明确包含这两个变量。
  • 规范化查询字符串: 标准化序列,摒弃无关参数,将相关参数列入白名单。
  • 设备和语言变体: 只有在明确分离(如通过子域、路径或显式 cookie)的情况下才能进行缓存;否则有可能出现密钥爆炸。
  • 正确设置 Vary 标头: Accept-Encoding for Gzip/Brotli,可选 Accept-Language, never Vary:*
  • 少吃饼干: 在决策中只包含那些真正影响显示效果的 cookies(如登录状态)。

这样可以防止缓存中毒,并控制对象变体的数量。更少的变体意味着更高的命中率和更低的存储成本。

新鲜、重新验证和陈旧的战略

我将 TTL 同时进行重新验证,以保持内容的新鲜和稳定。对于共享缓存,s-maxage 和缓存控制至关重要。此外,我还使用陈旧策略来继续快速响应上游问题。

  • s-maxage 与 max-age: s-maxage 控制共享缓存(代理、CDN),max-age 控制浏览器。对于 HTML,我通常将 s-maxage 设置为几分钟,将 max-age 设置为很短或为零。
  • stale-while-revalidate: 在后台进行更新时,用户会收到旧的响应。这明显缓解了负载高峰。
  • stale-if-error: 如果出现 5xx 错误,我会继续从缓存中提供服务,以掩盖故障。
  • use_stale/背景更新: 在 Nginx 中,我使用 use_stale 和后台更新;在 Apache 中,我使用 CacheStaleOnError 等选项。
  • ETag/Last-Modified: 如果客户端发送 If-None-Match/If-Modified-Since 而服务器返回 304,重新验证可节省带宽。

有了这种组合,即使在部署或短期上游延迟的情况下,我也能实现较短的响应时间和稳健的服务。

微缓存和拦截负载峰值

对于频繁查询但结果相似的高动态页面,我使用 微型寻宝 上。我将 HTML 结果缓存 1-10 秒,这样就能防止 1000 个类似查询同时进入应用程序。

  • 简短而有效: 3-5 秒的 TTL 可大大降低峰值负载,而用户不会注意到过时的内容。
  • 颗粒状: 只在热点(开始页、分类页、搜索建议)激活,而不是全局激活。
  • 个性化旁路 会话、购物车或登录 cookie 不包括微缓存。

在突发流量情况下,微缓存是降低成本和提高稳定性的有利手段。

避免缓存踩踏事件:锁定和限制

有一个 雷鸣炉 过期对象上同时运行许多请求。为了防止这种情况,我在创建新副本时阻止了请求。

  • Nginx: 为代理和 FastCGI 缓存激活 cache_lock,并合理选择超时时间。
  • 阿帕奇 使用 CacheLock,这样就不会让所有工作者同时运行应用程序。
  • 限制资源: 适当调整同时上游连接、工作者和队列深度。

此外,稍长的 s-maxage 加重新验证有助于确保对象很少同步从缓存中掉落。

决定:何时使用 Nginx,何时使用 Apache,何时使用 Varnish?

对于静态内容和有明确缓存规则的 PHP 应用程序,我通常使用 Nginx 和 FastCGI 缓存。对于包含许多模块、重写链和不同脚本语言混合操作的复杂应用程序设置,我经常使用 阿帕奇.如果我需要额外的边缘缓存或扩展策略,我会在前面放置一个反向代理。本指南提供了一个很好的设置起点: 设置反向代理.重要的是要正确确定优先级:首先是正确的应用程序标题,然后是服务器端缓存,最后是可选的代理层。

安全性和合规性:缓存中允许哪些内容?

敏感 数据 始终保持在外部:个人资料、购物篮、订单概览、票据、病人信息、管理区。我设置了清晰的缓存控制头,这样代理和浏览器就不会存储任何机密内容。对于 Cookie,我使用 SameSite、HttpOnly 和 Secure,并始终将个性化路径分开。我还记录异常访问,以便快速识别错误配置。这样既能保持高性能,又不会危及保密性。

实践中的页眉政策

我定义了一个一致的标题集,这样所有级别都能以相同的方式行事,不会发出相互矛盾的指令。

  • HTML(公开,但很短命): Cache-Control: public, s-maxage a few minutes, max-age rather 0-60s, must-revalidate if necessary; ETag/Last-Modified active.
  • 资产(长期): Cache-Control: public, max-age 1 year, immutable; 版本文件名(指纹),这样我就可以在不清除的情况下进行部署。
  • 个性化页面: Cache-Control: no-store, private; 仅在必要时使用 Set-Cookie。绝不共享授权标头。
  • 重定向和 404: 301 可能存活很长时间,302/307 只存活很短时间;404 缓存时间很短,因此错误不会被修复。
  • 压缩: 激活 Gzip/Brotli,并设置 Vary: Accept-Encoding,以便正确分隔变量。

这样,浏览器、代理服务器和服务器缓存的行为都是透明的。

与 CDN 和浏览器缓存的交互

我将服务器端 缓存 对于 HTML,我会在服务器上设置较短的 TTL,并在 CDN 中指定不同的规则。对于 HTML,我会在服务器上设置较短的 TTL,并在 CDN 中指定不同的规则。在浏览器中,我会控制 Expires、ETags 和 Cache-Control,这样返回的用户就无需重新加载太多内容。版本化的文件名(资产指纹)允许长时间运行,而不会出现错误。 目录.我通过缓存清除或新资产版本推出更改。

容量规划和存储调整

缓存只有在大小、内存布局和交换规则正确的情况下才会运行良好。我根据每个 TTL 的唯一对象数量及其平均大小来估算所需的容量,并为峰值规划一个缓冲区。在 Nginx 中,我会确定 keys_zone(RAM 中的索引)、inactive(无命中的进程)和 max_size(磁盘)。在 Apache 中,我会检查缓存路径、最大大小并使用工具进行清理。

  • 专用存储器: 为高速缓存分离卷/分区,以减少 IO 竞争。
  • 文件系统参数 noatime 等选项可以减少 IO 开销;大的 inodes/块可以更有效地容纳许多小文件。
  • 驱逐: 接受 LRU 策略并选择 TTL,以便保留热对象。
  • 预热: 部署后 Ping 重要路径,让用户立即受益。
  • htcacheclean/Manager: 在 Apache 下定期清理;在 Nginx 下不要阻碍缓存管理器进程。

内存和配置随着网站的增长而增长,因此点击率保持稳定。

操作、失效和维护

我计划明确 流程 在部署、内容更新和结构更改后进行缓存验证。自动钩子专门清除受影响的路径,而不是删除整个缓存。健康检查和警报会报告异常未命中率或错误代码,以便我立即做出反应。我将规则、职责和典型异常情况记录在案,以确保结果的一致性。这样就能保持系统的可预测性、快速性并便于团队维护。

无效方法和清除模式

清理选项因堆栈而异。我更喜欢不需要完全删除并能最大限度降低风险的策略。

  • 基于时间的失效: 短 s-maxage/TTL(HTML 加重新验证);由于资产是版本化的,因此可以保持较长的时间。
  • 关键版本: 将版本标记(如构建 ID)整合到缓存密钥中;版本在部署过程中会发生变化,旧对象过期后不会被清除。
  • 有针对性的清洗: 在可用的情况下,通过 API/PURGE 有选择性地删除;否则,有选择性地删除缓存文件并预热。
  • 在应用程序层面进行标记: 将页面分配到组/标签,并在更新内容时特别使组失效。
  • 在边缘禁止接近: 如果上游连接了专用反向代理,则会出现基于模式的阻塞。

我将 CI/CD 流程中的步骤自动化,并保留日志以跟踪内容何时以及为何失效。

测试和质量保证

在规则上线之前,我会确保其功能和安全性是正确的。我使用暂存环境,并进行明确定义的测试。

  • 标题检查: 每种资源类型的 Cache-Control、Vary、ETag/Last-Modified 是否正确?
  • 命中/失误分析: 更改是否会提高命中率?敏感页面是否会误入缓存?
  • 负载和错误案例: 峰值负载、上游超时和 5xx 下的行为--stale-if-error 是否生效?
  • 设备/语言变体: 变体是否正确分离并正确返回?
  • 与搜索引擎优化相关的路径: 301/302 处理、规范、分页和搜索页面未正确缓存。

我使用合成检查和真实用户指标来确保优化不会导致倒退。

简要概述

我使用服务器端 缓存以降低响应时间、减少服务器负载并轻松处理峰值负载。Nginx 的快速 FastCGI 和代理缓存、Apache 的可变模块逻辑和精细控制令人印象深刻。精确的 TTL、旁路和清除规则对保护个性化内容至关重要。有意义的监控 页眉 向我展示规则是否有效,以及我需要在哪些方面进行调整。有了简洁的配置、明确的例外情况和有计划的失效,每个网站都能保持快速、可靠和可扩展。

当前文章