网站缓存加速怎么做?三层配齐

前阵子帮朋友看他那个 WordPress 站,首页打开要四五秒,控制台里装了三四个缓存插件,一个个开着都说生效,结果一点没快。我上去翻了翻配置就明白了,他这属于典型的只装工具没分层:浏览器那层该管的静态文件没设过期时间,页面缓存和插件自带的缓存互相打架,数据库查询还是每请求跑一遍。缓存这事儿真不是装个插件就完事,得按层配齐,一层管一段,各干各的活。今天就把我自己一直在用的三层配置法摆出来,浏览器层、页面层、对象层,一层层说清楚,最后再教你怎么确认三层都真生效。

浏览器缓存

先搞明白为什么要分三层,而不是只装一个插件

我用下来最直观的感受是,很多人对缓存的想象太简单,觉得装个插件就全解决了。可实际上,一个页面从用户点开到屏幕上出现,中间至少要经过三段:文件在浏览器里缓不缓存、整个页面在服务器上有没有现成副本、生成页面时那些重复的数据库查询有没有被记住。三段对应三种完全不同的机制,谁也不能替谁干活。浏览器缓存省的是重复下载,页面缓存省的是 PHP 执行,对象缓存和 OPcache 省的是数据库和编译开销。只做其中一层,另外两层照样卡着,你自然会觉得折腾了半天没效果。所以我建议的动手顺序也是从浅到深,一层配完验一层,别一口气全上。

第一层浏览器缓存:在 Nginx 里给静态资源设过期时间

这层最省事,也最容易被忽略。目标就一个:让 jpg、png、css、js 这类几乎不变的文件,在用户浏览器里待着别来回下载。做法是在站点的 Nginx 配置里加 location 块,按后缀匹配,统一加上 expires 30d 和 Cache-Control 头。举个例子,写一个 location 匹配以 jpg、jpeg、png、gif、webp 结尾的请求,里面配好过期天数,再配一段匹配 css 和 js,样式表和脚本一般改得稍微勤一点,给个 7d 到 30d 都行。写完别急着重载,先跑一遍 nginx -t 看语法有没有写错,没问题再平滑重载,线上不会断。想更细一点,字体文件、视频文件也可以各自加一段,思路完全一样。

顺带把两件常被问的事讲透。一是 expires 和 Cache-Control 谁说了算:前者是 HTTP 1.0 留下的头,值是具体时间点;后者是 1.1 的头,直接说这个资源还能用多少秒,相对时间更靠谱,不怕服务器和客户端的钟表对不上。两者同时存在时浏览器以 Cache-Control 为准,所以我的习惯是两个都写上,反正 Nginx 一个指令就顺手带了。二是缓存到期不等于必须重新下载整个文件,浏览器多半会发个带校验信息的请求问服务器变没变,服务器回一个 304 让它继续用本地副本,这一来一回流量小得多。看到 304 是好事,别以为配置没生效。

设 30d 之前先想清楚:改了文件用户看不到怎么办

30 天这个数字挺诱人,但有个前提得先解决,就是文件名要带指纹。不少朋友图省事,样式表永远叫 style.css,脚本永远叫 main.js,内容一改文件名不变,浏览器手里那份三十天不过期,用户看到的还是旧样式。这类问题最后都变成一句经典的抱怨:我这儿明明是好的,怎么你那儿没变。解决办法是让文件名带上版本号或者一串哈希值,主题和构建工具基本都支持,WordPress 里给静态资源加版本号也是常规操作。还有一种情况是把自己写的文件放进主题目录,被主题更新覆盖掉了,建议放子主题里,升级不丢配置。文件带指纹就大胆设 30d,不带就老实设短一点,别为难自己。

第二层页面缓存:fastcgi_cache 或 proxy_cache 怎么开

这层省下的时间最实在。页面缓存本质上是在服务器上留一份 PHP 执行完的 HTML,下次同样的请求进来直接吐出去,PHP 和数据库都不用惊动。Nginx 提供两条路:PHP 跑在本机 PHP-FPM 上,就用 fastcgi_cache;前面还挂了一层后端服务,就用 proxy_cache。配置分两截,先在 http 块里声明缓存路径和内存区域,再用一个指令在 PHP 处理的那个 location 里打开它。key 决定什么算同一个页面,建议把请求方法、主机名和请求地址拼进去,少了主机名容易出现多域名共用一份缓存、串站的麻烦。再配一条 fastcgi_cache_valid,让状态码是 200 的响应缓存 10 分钟,对内容站够用。

登录用户和购物车页,一定要用 bypass 放过去

页面缓存最怕的就是把不该缓存的页面缓存了。登录用户的页面里带着用户名和后台管理条,要是这份 HTML 被缓存下来,下一个人访问直接就看到了,这是最典型的隐私事故。Nginx 给了两个配套指令,fastcgi_cache_bypass 管读,命中条件就不读缓存直接回源,fastcgi_no_cache 管写,命中条件就不把响应存进缓存。两者方向相反,最稳的写法是让它们用同一套判断条件。我的判断有两项,一是请求里有没有登录 cookie,二是请求地址是不是命中后台、登录、购物车、结算这几个路径,命中就跳过。做电商的站还得看购物车相关的 cookie,不能只判断登录状态,因为没登录的人也可能往车里加东西。这两条规则配好,页面缓存才算用明白。

第三层对象缓存:Redis 配 OPcache,一个管数据一个管代码

前两层做完,静态文件和整页都缓存了,但页面本身还是得生成一次,生成过程里的数据库查询还在一次次重复。WordPress 每次请求都要查菜单、选项、小工具、文章列表,这些数据基本不变,查一遍就够了。装 Redis 再把 object-cache.php 这个文件扔进 wp-content 目录,就相当于把 WordPress 的对象缓存接口接管了,查询结果先看内存里有没有,有就直接拿。这里有个细节要注意,文件必须直接放进 wp-content 下,不是放进插件目录,这种不改代码就接管的机制官方叫 drop-in,页面加载时优先读它。连接信息写进 wp-config.php 里,别硬编码在那个文件里,换机器或者改密码时只改一处。改完记得清一次旧缓存再验证。

对象缓存管的是数据,OPcache 管的是代码,两者不冲突,可以一起开。PHP 每次执行脚本都要先编译成中间码,同一份代码被访问一千次就编译一千次,纯属白费力气。OPcache 打开以后编译结果留在共享内存里,后面直接取用。在 php.ini 里把对应的开关打开,脚本数量上限、内存大小按站点规模调一调,改完重启 PHP 服务。有个坑得提醒,开发环境不建议开,否则改了代码看不到变化,会以为是代码写错了,白折腾半天。线上环境则相反,检查间隔调大一点更划算。想确认有没有生效,后台的健康检查页或者 PHP 信息页里翻一翻,会写明缓存命中了多少脚本。

三层都配好了,怎么确认各自真的在干活

配完不验证等于没配,这部分最容易被跳过。第一步用 curl -I 看你那个静态资源的地址,响应头里应该有 Cache-Control 和 expires 两行,值是你设的天数,同时留意有没有别的层把值改小了。第二步打开开发者工具的 Network 面板,刷新页面,看 Size 那一列:写着 from memory cache 说明这次连本地磁盘都没读,直接从内存里拿的;写着 from disk cache 说明走了磁盘;只有出现真实字节数才是真下载。第三步给页面缓存加个自定义响应头,命中时做个标记,再用 curl 请求同一地址两次,第二次应该能看到标记。对象缓存和 OPcache 不在响应头里,去看 Redis 里的键数量和后台的查询次数,配上对象缓存后正常会明显往下掉。

常见的互相覆盖:三层为什么会打架

最后说说打架这事,确实很常见。最典型的是把所有页面都设成缓存一个月,连登录页、后台、动态接口都算进去,结果就是内容更新了用户看不到,后台提示也永远是旧的。还有人页面缓存开着,又装了别的缓存插件,两套规则一起写响应头,浏览器到底听谁的全凭运气。判断标准其实很简单:浏览器缓存只负责带指纹的静态文件,时长可以给长;页面缓存只覆盖匿名访问的普通页面,用跳过规则放行登录和购物车;对象缓存和 OPcache 是后台减负,不碰响应头。三者的作用范围不重叠,就不会互相覆盖。真要排查,就把某一层临时关掉再测同一地址,对比响应头和数据变化,一眼就能看出是谁在捣乱。

捋一遍:浏览器层在 Nginx 里用 location 匹配后缀,配上 30 天的过期时间和缓存控制头;页面层开 fastcgi_cache 或 proxy_cache,定好 key 和十分钟的有效期,再用跳过规则把登录用户、后台和购物车放过去;对象层装 Redis 并把 object-cache.php 放进 wp-content,同时把 OPcache 打开。三层各管一段,从浅到深一层层配,配一层验一层,最后用响应头和开发者工具把每一层都确认一遍,这活儿就算干利索了。真正提速靠的是这种踏实的配置,而不是插件装得多。

【版权声明】:本站所有内容均来自网络,若无意侵犯到您的权利,请及时与我们联系将尽快删除相关内容!

(0)
爱家的头像爱家
数据库用什么软件管?远程连接别裸奔
上一篇 2026-09-14 08:25
负载均衡器通常位于网络架构的哪一层?
下一篇 2025-01-12 12:23

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

广告合作

QQ:14239236

在线咨询: QQ交谈

邮件:asy@cxas.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信