WordPress 网站接了 Cloudflare 还是慢?Nginx + Redis 缓存从 0 搭到秒开(含自动清缓存)

封面图
你接了 Cloudflare,开了代理,觉得网站该快了——打开首页,转了 3 秒。问题不在 Cloudflare,在于 Cloudflare 默认不缓存 HTML。你的动态页面每次都要回源,走一遍 PHP + MySQL,TTFB 自然降不下来。这篇文章教你把 WordPress 缓存从 0 搭到完整,最终效果:

  • TTFB 从 1 ~ 3 秒降到 50 ~ 300 ms
  • HTML 页面真正命中缓存
  • 发布新文章后缓存自动刷新
  • 登录用户和后台永远不缓存

适用环境: 宝塔面板 + Nginx + WordPress + Cloudflare(4 核 8G 及以上服务器)


最终架构长什么样

先看全局,再一步步配。

用户请求
  ↓
Cloudflare(CDN + HTML 缓存,TTL 10 分钟)
  ↓
Nginx FastCGI Cache(页面级缓存,10 分钟)
  ↓
PHP-FPM
  ↓
Redis Object Cache(数据库查询缓存)
  ↓
MySQL

每一层解决不同的问题:

缓存层 缓存什么 TTL 不缓存什么
Cloudflare HTML 页面、静态资源 HTML 10 分钟,静态 30 天 wp-admin、登录态
Nginx FastCGI Cache PHP 渲染后的 HTML 10 分钟 POST 请求、后台、登录 Cookie
Redis Object Cache 数据库查询结果 按对象 TTL 无(自动管理)
浏览器 CSS/JS/图片 30 天 HTML(no-cache)
四层缓存架构图

核心逻辑:Cloudflare 和 Nginx 都缓存 HTML,但都跳过登录用户和后台。Redis 在数据库层减少重复查询。

下面开始配置。


第一步:安装 Redis 并启用 Object Cache

Redis 缓存数据库查询结果,减少 WordPress 每次请求都打 MySQL 的问题。

1.1 宝塔安装 Redis

宝塔面板 → 软件商店 → 搜索 Redis → 安装。

推荐版本:Redis 7.x

1.2 安装 PHP Redis 扩展

宝塔面板 → 软件商店 → 你用的 PHP 版本 → 设置 → 安装扩展 → 找到 redis → 安装。

1.3 WordPress 安装 Redis Object Cache 插件

后台 → 插件 → 安装插件 → 搜索 Redis Object Cache → 安装并启用。

进入 设置 → Redis → 点击 Enable Object Cache

状态显示 Connected 就对了。


第二步:配置 Nginx FastCGI Cache

这是最关键的一步。配置完后,Nginx 会把 PHP 渲染出的 HTML 缓存到磁盘,下次请求直接返回,不再走 PHP。

2.1 编辑 nginx.conf

文件路径:

/www/server/nginx/conf/nginx.conf

http { 下面添加:

# FastCGI Cache 配置
fastcgi_cache_path /tmp/nginx_cache levels=1:2 keys_zone=WORDPRESS:100m inactive=60m;

# 登录限速(防暴力破解)
limit_req_zone $binary_remote_addr zone=one:10m rate=1r/s;

参数说明:

  • keys_zone=WORDPRESS:100m — 缓存索引区 100MB,够用
  • inactive=60m — 60 分钟没人访问就清除
  • levels=1:2 — 两级目录结构,避免单目录文件过多

2.2 创建缓存目录

mkdir -p /tmp/nginx_cache
chmod -R 777 /tmp/nginx_cache

2.3 编辑网站 Nginx 配置

文件路径:

/www/server/panel/vhost/nginx/你的域名.conf

完整配置如下(把 www.example.com 和路径替换成你自己的):

server {

    listen 80;
    listen 443 ssl http2;

    server_name www.example.com;
    root /www/wwwroot/www.example.com;
    index index.php index.html index.htm;

    # ===== SSL =====
    ssl_certificate /www/server/panel/vhost/cert/www.example.com/fullchain.pem;
    ssl_certificate_key /www/server/panel/vhost/cert/www.example.com/privkey.pem;
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_session_timeout 1d;
    ssl_session_cache shared:SSL:10m;
    ssl_prefer_server_ciphers on;
    add_header Strict-Transport-Security "max-age=31536000" always;

    # ===== GZIP =====
    gzip on;
    gzip_comp_level 6;
    gzip_min_length 1k;
    gzip_types
        text/plain
        text/css
        text/javascript
        application/javascript
        application/json
        application/xml
        image/svg+xml;

    # ===== 上传限制 =====
    client_max_body_size 100m;

    # ===== WordPress Rewrite =====
    location / {
        add_header Cache-Control "no-cache, must-revalidate";
        try_files $uri $uri/ /index.php?$args;
    }

    # ===== 静态资源缓存 =====
    location ~* .(jpg|jpeg|png|gif|ico|css|js|svg|woff|woff2|ttf|webp)$ {
        expires 30d;
        access_log off;
        log_not_found off;
        add_header Cache-Control "public, immutable";
    }

    # ===== robots / favicon =====
    location = /robots.txt {
        access_log off;
        log_not_found off;
    }
    location = /favicon.ico {
        access_log off;
        log_not_found off;
    }

    # ===== 禁止敏感文件 =====
    location ~ /.(ht|git|env) {
        deny all;
    }

    # ===== 禁止上传目录执行 PHP =====
    location ~* /(?:uploads|files)/.*.php$ {
        deny all;
    }

    # ===== Let's Encrypt =====
    location ~ /.well-known {
        allow all;
    }

    # ===== 登录限速 =====
    location = /wp-login.php {
        limit_req zone=one burst=5 nodelay;
        include fastcgi.conf;
        fastcgi_pass unix:/tmp/php-cgi-74.sock;
    }

    # ===== PHP + FastCGI Cache =====
    location ~ .php$ {
        include fastcgi.conf;
        fastcgi_pass unix:/tmp/php-cgi-74.sock;
        fastcgi_index index.php;

        # 默认缓存
        set $skip_cache 0;

        # POST 请求不缓存
        if ($request_method = POST) {
            set $skip_cache 1;
        }

        # 只排除特定参数(不要排除所有 query_string)
        if ($query_string ~* "preview=true|nocache") {
            set $skip_cache 1;
        }

        # 后台和特殊路径不缓存
        if ($request_uri ~* "/wp-admin/|/wp-login.php|/xmlrpc.php|/feed/|sitemap(_index)?.xml") {
            set $skip_cache 1;
        }

        # 登录用户不缓存
        if ($http_cookie ~* "wordpress_logged_in|comment_author|woocommerce_items_in_cart") {
            set $skip_cache 1;
        }

        # FastCGI Cache 核心
        fastcgi_cache WORDPRESS;
        fastcgi_cache_valid 200 301 302 10m;
        fastcgi_cache_bypass $skip_cache;
        fastcgi_no_cache $skip_cache;

        fastcgi_cache_use_stale
            error
            timeout
            invalid_header
            updating
            http_500
            http_503;

        add_header X-Cache $upstream_cache_status;
    }

    # ===== Cloudflare Real IP =====
    real_ip_header CF-Connecting-IP;
    set_real_ip_from 173.245.48.0/20;
    set_real_ip_from 103.21.244.0/22;
    set_real_ip_from 103.22.200.0/22;
    set_real_ip_from 103.31.4.0/22;
    set_real_ip_from 141.101.64.0/18;
    set_real_ip_from 108.162.192.0/18;
    set_real_ip_from 190.93.240.0/20;
    set_real_ip_from 188.114.96.0/20;
    set_real_ip_from 197.234.240.0/22;
    set_real_ip_from 198.41.128.0/17;
    set_real_ip_from 162.158.0.0/15;
    set_real_ip_from 104.16.0.0/13;
    set_real_ip_from 104.24.0.0/14;
    set_real_ip_from 172.64.0.0/13;
    set_real_ip_from 131.0.72.0/22;

    # ===== 错误页 =====
    error_page 404 /404.html;
    error_page 500 502 503 504 /502.html;

    access_log /www/wwwlogs/example.log;
    error_log /www/wwwlogs/example.error.log;
}

注意: fastcgi_pass 后面的 socket 路径要和你 PHP 版本对应。比如 PHP 7.4 是 php-cgi-74.sock,PHP 8.1 是 php-cgi-81.sock。在宝塔面板的 PHP 设置里可以确认。

2.4 测试并重启 Nginx

nginx -t

显示 syntax is oktest is successful 后:

service nginx restart

第三步:配置 Cloudflare Cache Rules

Cloudflare 默认只缓存静态资源。要让 HTML 也缓存,必须手动加 Cache Rules。

3.1 SSL/TLS 设置

Cloudflare → SSL/TLS → 设置为 Full (strict)

不要用 Flexible,否则 Cloudflare 和你服务器之间走 HTTP,既不安全也可能出重定向循环。

3.2 Speed Optimization

Cloudflare → Speed → Setting:

  • HTTP/3:开启
  • Early Hints:开启

3.3 添加 Cache Rules

进入 Cloudflare → Caching → Cache Rules。

规则按顺序添加,Cloudflare 从上往下匹配,先写排除规则,再写缓存规则

规则 1:后台不缓存

表达式:

(http.request.uri.path contains "/wp-admin")

操作:绕过缓存

规则 2:登录页不缓存

表达式:

(http.request.uri.path contains "/wp-login.php")

操作:绕过缓存

规则 3:预览页面不缓存

表达式:

(http.request.uri.path contains "/preview")
or
(http.request.uri.path contains "preview=true")

操作:绕过缓存

避免 WordPress 文章预览被缓存,导致你看到的永远是旧版本。

规则 4:静态资源缓存 30 天

表达式:

(http.request.uri.path.extension in {"js" "css" "png" "jpg" "jpeg" "gif" "ico" "svg" "woff" "woff2" "ttf" "webp"})

操作:

  • 符合缓存条件
  • Edge TTL:30 天
  • 浏览器 TTL:30 天

静态资源变更频率低,缓存 30 天可以大幅减少回源。如果你用了文件名哈希(如 style.a1b2c3.css),可以直接缓存到 1 年。

规则 5:HTML 页面缓存 10 分钟

表达式:

(http.host eq "www.example.com")
and
(not http.cookie contains "wordpress_logged_in")
and
(not http.request.uri.path contains "/wp-admin")
and
(not http.request.uri.path contains "/wp-login.php")
and
(not http.request.uri.path contains "/preview")

操作:

  • 符合缓存条件
  • 忽略缓存控制头(Override origin)
  • Edge TTL:10 分钟

这条规则是核心。它让 Cloudflare 把 HTML 页面缓存 10 分钟,但排除已登录用户和后台。忽略缓存控制头是因为 WordPress 默认会给 HTML 加 no-cache,不覆盖的话 Cloudflare 不会缓存。

规则顺序很重要。 Cloudflare 按从上到下的顺序匹配,匹配到第一条就停止。所以"不缓存"的规则必须放在"缓存"的规则上面。

Cloudflare Cache Rules 优先级匹配图


第四步:安装自动 Purge 插件

缓存配好了,但有个问题:发布新文章后,首页和文章页还是旧缓存。

必须让发布内容时自动清缓存。需要两个插件配合。

4.1 Nginx Helper — 清 Nginx 层缓存

后台 → 插件 → 安装 Nginx Helper → 启用。

进入 设置 → Nginx Helper:

  • Enable Purge:勾选
  • Caching Method:选择 nginx Fastcgi cache
  • Purge Method:选择 Delete local server cache files

保存。

4.2 Cloudflare 插件 — 清 Cloudflare 层缓存

后台 → 插件 → 安装 Cloudflare → 启用。

创建 API Token:

  1. 打开 Cloudflare API Tokens
  2. Create Token → 选择 WordPress 模板
  3. 确保权限设置:
    • Zone → Cache Purge → Purge
    • Zone → Zone → Read
  4. 复制 Token

插件配置:

  1. 进入 WordPress 后台 → Cloudflare 设置
  2. 填入 Email 和 API Token
  3. 开启 Auto Purge Content On Update

这样每次发布或更新文章,Cloudflare 对应页面的缓存会自动清除。


第五步:验证缓存是否生效

配置完不代表生效了。用以下方法逐层验证。

5.1 验证 Nginx FastCGI Cache

用浏览器访问首页(无痕模式,确保没登录),按 F12 → Network → 刷新页面 → 点第一个请求 → 查看 Response Headers。

找到:

x-cache: HIT
  • HIT = 缓存命中,Nginx 直接返回了缓存
  • BYPASS = 跳过缓存(登录了或命中了排除规则,正常)
  • MISS = 第一次访问,还没有缓存。再刷一次,应该变成 HIT

5.2 验证 Cloudflare 缓存

同样的 Response Headers 里找:

cf-cache-status: HIT
  • HIT = Cloudflare 缓存命中
  • MISS = 第一次,再刷一次看
  • BYPASS = 被你的 Cache Rule 排除了(检查是不是后台或登录状态)

5.3 验证 Redis

WordPress 后台 → 设置 → Redis → 状态页。

查看:

  • Hits 应该在增长
  • Hit Ratio 应该 > 80%
  • Connected 状态

5.4 验证自动 Purge

  1. 发布一篇新文章
  2. 无痕模式打开首页
  3. 看新文章是否立即出现
  4. 检查 Response Headers,cf-cache-statusx-cache 是否显示 MISS(说明缓存被清过,重新生成了)

我踩过的三个坑

配置过程中最容易翻车的三个地方。

坑 1:Cloudflare 缓存了登录态页面

现象: 无痕模式打开网站,页面上居然显示你的用户名。

原因: Cloudflare Cache Rules 里没有排除 wordpress_logged_in Cookie。你登录状态下访问的页面被 Cloudflare 缓存了,其他访客看到的也是你登录后的页面。

修复: Cache Rule 表达式里必须加上:

not http.cookie contains "wordpress_logged_in"

这个必须加,不加就是安全事故。

坑 2:FastCGI Cache 一直 BYPASS

现象: 怎么刷 x-cache 都是 BYPASS

原因: query_string 的排除条件写太严了。我最开始写的是:

if ($query_string != "") {
    set $skip_cache 1;
}

这意味着任何带参数的请求都不缓存。但现实中 UTM 参数(utm_sourcefbclidgclid)到处都是,导致大量正常流量命中不了缓存。

修复: 只排除真正需要跳过的参数:

if ($query_string ~* "preview=true|nocache") {
    set $skip_cache 1;
}

改完后缓存命中率直接上去了。

坑 3:ssl_session_cache 冲突

现象: nginx -t 报错 shared memory zone "SSL" conflicts

原因: 服务器上有多个网站,每个网站的 Nginx 配置里都写了:

ssl_session_cache shared:SSL:10m;

同一个 shared zone 名字在不同配置里大小不一样就会冲突。

修复: 所有网站的 ssl_session_cache 统一成相同大小,或者只在 nginx.confhttp {} 里写一次。


优化前后对比

指标 优化前 优化后
TTFB 1~3 秒 50~300ms
CPU 占用 频繁飙升 非常低
HTML 缓存 不命中 命中
后台操作 偶尔卡顿 流畅
发布新文章 首页长时间不更新 立即更新
优化前后对比

上线前检查清单

逐条确认,全打勾再上线。

  • Redis 已安装,PHP Redis 扩展已启用
  • Redis Object Cache 插件状态为 Connected
  • nginx.conf 里添加了 fastcgi_cache_path
  • /tmp/nginx_cache 目录已创建,权限 777
  • 网站 Nginx 配置里 fastcgi_pass 路径和 PHP 版本匹配
  • nginx -t 测试通过
  • Cloudflare SSL/TLS 设为 Full (strict)
  • Cloudflare Cache Rules 添加了五条规则(后台排除、登录排除、预览排除、静态资源缓存、HTML 缓存)
  • Cache Rule 排除了 wordpress_logged_in Cookie
  • Nginx Helper 已启用,Purge Method 设为 Delete local server cache files
  • Cloudflare 插件已配置 API Token,Auto Purge Content On Update 已开启
  • 无痕模式访问首页,x-cache: HIT
  • 无痕模式访问首页,cf-cache-status: HIT
  • 发布测试文章,无痕模式验证首页立即更新
  • 后台页面没有被缓存(cf-cache-status: BYPASS

适用范围

这套方案适用于:

  • 宝塔面板 + Nginx + WordPress
  • 服务器 2 核 4G 及以上(Redis 占用内存不大)
  • Cloudflare 免费版即可(Cache Rules 免费版有 10 条额度,够用)

不适合:

  • 使用 Apache / OpenLiteSpeed 的环境(Nginx FastCGI Cache 是 Nginx 专属)
  • 超大流量站点(日 PV 50 万+,建议考虑 Redis 页面缓存或 CDN 全量回源方案)
  • 使用页面缓存插件(如 WP Rocket)且功能冲突时(选一套,不要叠)

如果你的 WordPress 还在裸奔——没有 Redis、没有页面缓存、Cloudflare 只开了代理——按这篇配完,体感提升会非常明显。

声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。