Contents
1 前言
在我之前的多活架构部署实践中(详见:家庭数据中心系列 WordPress多活架构(简版)在个人博客中的落地方案),Cloudflare 的运行状况检查(Health Checks)是实现节点可用性判断的核心机制之一,之前我博客的运行状况检查的内容如下:

上图中使用的检查路径是 “/healthcheck”,这是我专门创建的一个 WordPress 页面,内容非常简单,只输出一段“OK”文本,便于 Cloudflare 定期发起 HTTP 请求来确认站点是否存活:

同时,我也在 Cloudflare 的规则中为该路径设置了绕过缓存、防火墙、安全挑战等策略,以尽可能确保响应结果能真实反映源站状态。
这种方案功能上是可行的,也确实稳定运行了一段时间。但在进一步分析和优化中,我发现这种方式其实存在不少隐藏的结构性问题:
- 首先,这个路径返回的是 200 状态码,并且带有正文内容,虽然响应体很小,但本质上仍然是一次完整的 WordPress 加载流程,服务器仍需经历路由解析、插件加载、模板渲染等步骤,不够轻量。
- 其次,这是一个“人为构造”的页面路径,WordPress 本身并没有内建语义,未来如果站点结构变动或路由被重写,很容易因为疏忽造成路径失效,但 Cloudflare 并不会立即感知这种异常。
- 最关键的是,由于这个路径返回的是 200 状态码,即使 WordPress 在内部出现了严重错误(如某个插件触发 PHP 报错),只要没有显式抛出 5xx,Cloudflare 的健康检查仍会判定为“成功”,这就可能出现“假阳性”——表面可用,实则已挂。
此外,由于是 WordPress 页面,这种方案还不可避免地受制于 WordPress 本身运行时机制与插件干预,进一步增加了不确定性:
- 页面最终由 WordPress 的前端路由控制,哪怕你页面里没有正文内容,WordPress 仍然会加载所有插件、主题钩子、路由逻辑,导致性能开销不必要地拉高。
- 像 Rank Math 这类 SEO 插件,会自动向页面注入结构化数据(如 JSON-LD),即使你页面没有正文,也可能在
<head>部分添加大量 schema 数据,这些内容对健康检查无用,反而增加了响应大小。 - 即使你启用了缓存绕过规则,Cloudflare APO 或某些插件缓存仍可能“偷偷缓存”页面响应,特别是在某些路径、参数未命中规则的边缘场景中,导致检查结果不能真实反映源站状态。
综上所述,这种“用页面模拟健康检查”的方案虽然简洁直观,但它无法完全绕开 WordPress 的内部运行机制,仍存在不少不可控因素。尤其在涉及多活、高可用、CDN 加速等复杂部署场景时,这类方案更容易因缓存干扰、插件注入或路由失效而误判服务状态,并不是一个理想的长期方案。
2 启发来源
本来,即便使用自定义页面做健康检查会有一些小缺陷,但是总体上来说,还是能够正常使用的,以我这么懒的性格,也不会去没事找事的研究新方法。
不过,后来无意中发现,不少软件,比如shadowsocket,在对各个节点进行可用性测试的时候,使用了这个URL:”http://www.gstatic.com/generate_204“:

还有merlin clash2也是一样:

这就让我有点兴趣了,为什么这些软件都用”http://www.gstatic.com/generate_204“这个链接作为测试链接呢?它到底有什么特别之处,能让这么多工具都拿它作为“判断网络是否畅通”的标准?
于是我查了下这个地址的背景,意外地发现,这个链接并不是某个无名小站的临时产物,而是 Google 专门为 Android 网络状态检测设计的一个“无内容”探测接口:它的返回非常“干净”——不会重定向、不携带正文、不触发缓存、更不会被运营商劫持(至少在不少地区是这样),响应码固定为 204 No Content,毫无多余开销,纯粹就是“你打到了这个地址,说明你能联网了”。
和我原来自己创建的“健康检查”页面/healthcheck相比,这种方式显然更轻、更快、更标准,也更难被运营商篡改或污染。
更重要的是,它启发了我一个想法:既然 Google 能做这样一个几乎“完美”的网络探测端点,那我是不是可以模拟这个 generate_204 的响应逻辑,部署在自己博客的不同节点上(不一定非要绑定在某个实际页面上),用作统一的探测端点供cloudflare的运行状况检查使用?
3 构建我博客的 generate_204:实现思路构想
根据文章前面的分析,要在我的博客上实现 generate_204 的响应逻辑,WordPress 自带的「文章」和「页面」都不适合。主要问题是:它们天生是为人类访问者设计的,而不是为网络探测程序服务,尤其在重写规则、URL 匹配和响应体控制上,存在先天限制。
那么,还有哪些更合适的路径可以选择呢?
我大致梳理了三种可能的实现方式:
- 站点级处理方式:
即绕过 WordPress,在 Web Server 层直接处理 /generate_204 路径。这种方式的最大优势是性能好、独立性高,但也意味着脱离了 WordPress 的统一管理体系。对于依赖插件自动化、统一配置的博客环境来说,这种割裂式的管理方式在维护上成本较高,未来扩展时也不够灵活。
- 主题级逻辑注入:
在当前主题的 functions.php 或其它 Hook 点中注入逻辑,实现对 /generate_204 请求的识别与响应。这种方式的适配性较好,也能获得 WordPress 环境变量的帮助。但我对主题的维护持极简态度,不希望这些功能逻辑污染主题,因此没有采用。
- REST API 路由注册(插件方式):
通过 WordPress 插件的形式,添加一个可响应的伪页面路径(比如 /generate_204)。插件会注册一个自定义的 REST API 路由,并监听该路径的请求,在请求到来时直接返回定制的响应内容。这种方式既符合 WordPress 的扩展机制,又能让代码结构清晰、职责单一,便于管理和维护,特别适合实现健康检查这类长期稳定运行的功能。
最终,我选择了第 3 种方式:以插件形式添加可响应的伪页面路径,并在插件内实现 /generate_204 的完整逻辑。 原因很简单:这种方式既不依赖 Web Server 层的额外配置,也不会污染我的主题代码,还能保持逻辑清晰、功能独立,非常契合我当前博客架构的原则。
4 实现方式详解:REST API 路由注册(插件方式)
4.1 概述
既然目标是提供一个返回 204 No Content 的探活接口,可以完全利用 WordPress 自带的 REST API 系统来实现这一需求。WordPress 的 REST API 是一个功能完备、拓展性很强的机制,允许我们方便地注册自定义路由,而不需要额外引入任何插件或改动核心代码。
在这个接口的设计上,我尽量保持“干净”和“隐蔽”两个原则:一方面,它只响应最简单的 GET 请求,不接收参数,不返回正文,唯一的意义就是活着;另一方面,它不要求任何认证验证,同时使用了一个不容易被猜测到的路径(比如 /wp-json/healthmonitor/check),避免落入通用扫描器的探测模式。这个接口本质上是为机器准备的,不应该暴露太多信息,更不应该暴露后台结构。
有意思的是,204 这个状态码常用于“处理成功,但没有返回内容”,比起 200 OK 少了一点 HTTP 报文的冗余,也让各种自动化系统可以更快地完成检查过程,从“效率”角度看,是非常合适的选择。
4.2 插件方式的优势
采用插件的形式来实现这个自定义探活接口,相比直接修改主题代码或依赖 Web Server 重写规则,有几个非常突出的优点:
- 它具备良好的结构独立性,所有逻辑都被封装在插件中,既不会污染主题目录,也避免了把代码塞进 functions.php 里造成混乱,这对于后续维护和协作开发尤为重要。
- 这种方式在部署上更加简单直接,无需去调整 Nginx 或 Apache 的 rewrite 规则,也不需要设置额外的服务器路径映射,只要插件启用,接口自然生效,哪怕部署在各种不同主机或面板环境中也能保持一致的表现。
- 插件的可迁移性也是一大优势,将来如果博客需要更换服务器、域名甚至整个架构,只要插件文件还在,无需额外配置,探活接口就可以继续使用。这种“带得走”的特性非常契合现代博客的可移植性需求。
- 在安全性方面也体现了插件方式的优势,可以通过 permission_callback 显式声明这个路由无需任何认证,让接口始终对外可访问,避免默认情况下 WordPress REST API 仅对登录用户开放的限制,也防止了可能出现的权限误判问题。在保持接口开放的同时,也最大限度地控制了访问权限的明确边界。
4.3 插件代码实现
为了实现一个专用于健康检查的探活接口,我们可以自定义一个极其简单的 WordPress 插件。
首先,在 WordPress 的插件目录中创建一个子目录,例如命名为:
/wp-content/plugins/wp-healthcheck-rest/
然后在该目录下创建一个名为 wp-healthcheck-rest.php 的插件主文件,内容如下:
<?php
/**
* Plugin Name: WP Healthcheck 204 (REST API)
* Description: 提供一个用于健康检查的 REST API 接口,返回 HTTP 204,无正文。推荐用作 WordPress 探活/状态检查。
* Version: 1.0
* Author: tangwudi
*/
add_action('rest_api_init', function () {
register_rest_route('healthmonitor', '/check', [
'methods' => 'GET',
'callback' => function () {
return new WP_REST_Response(null, 204);
},
'permission_callback' => '__return_true',
]);
});
这段代码完成了以下工作:
- 使用 rest_api_init Hook 注册 REST 路由;
- 路由路径为 /wp-json/healthmonitor/check;
- 设置请求方法为 GET;
- 响应函数直接返回一个空内容的 WP_REST_Response,状态码为 204;
- 设置 permission_callback 为 __return_true,即接口无需权限校验,任何人都能访问。
将这个插件文件放置到 wp-healthcheck-rest 目录中后,登录 WordPress 后台启用插件即可:

此时,我们就拥有了一个稳定可靠、符合标准的探活接口,适用于各类负载均衡器、监控系统或自动化平台调用。
5 实际效果验证
部署完成后,可以直接使用浏览器访问如下地址进行验证:
http(s)://你的域名/wp-json/healthmonitor/check
不过,使用浏览器访问的结果是页面一闪就没了,不好截图,所以换个方法,可以使用最简单的 curl 命令进行验证:
curl http(s)://你的域名/wp-json/healthmonitor/check
此时你将会看到终端无任何输出:

虽然表面上看似“什么都没有返回”,但这正是 HTTP 204 No Content 的特性 —— 请求成功,但服务器明确表示没有响应体。为了验证这一点,我们可以加上 -i 参数查看响应头信息:
curl -i http(s)://你的域名/wp-json/healthmonitor/check
返回内容如下:

从输出中可以看到几个关键点:
- HTTP 状态码为 204,表示请求处理成功,但不会返回任何内容;
- 响应体确实为空,你不会在终端看到任何正文,光标直接换行结束;
- 响应头中可能包含如 Set-Cookie、Cache-Control 等字段,体现了真实的服务运行环境,但不会影响 body 的“空白”。
在使用这个 REST 路由前,我博客使用一个自定义页面 /healthcheck 作为探活接口。我们也用相同的方式来对比下它的表现,使用最简单的 curl 命令,终端中直接输出的是大量 HTML 内容(以下仅为第一页截图,后面还有十多页,就不一一截图了):

再来看带响应头的输出
-i,一样有十多页输出,这是第一页:
虽然技术上这也可以用于存活探测,但它存在几个明显问题:
- 返回的是 HTTP 200,不是专为探活设计的语义;
- 响应体是完整 HTML 页面,即便很简单,也比 204 响应臃肿很多;
- 主题模板、缓存、SEO 插件等都可能影响返回内容,带来不可预期变数;
- 某些反代工具或健康检查系统(如 Cloudflare 的运行状况检查)会误判页面内容异常,从而导致误报,这点我之前使用
/healthcheck页面时就深受其害; - 在运维平台、负载均衡器等系统中集成也不够“语义清晰”。
相比之下,/wp-json/healthmonitor/check 返回的 204 响应非常干净、精确、可靠,完全符合现代 Web 架构中对“无副作用探活接口”的最佳实践——它不会返回任何响应体,状态码明确表达“服务在线但无需返回内容”,这使得它既避免被 Cloudflare APO、WordPress 缓存插件等静态缓存机制缓存,又能最大限度减少带宽和响应时间的浪费,是更纯粹、更稳定的健康检查形式。
6 总结
探活接口这件事,乍一看像是个无足轻重的小细节,但实际往往是架构演进中的一块基石——尤其当我们开始用 Cloudflare Tunnel 做入口、用 GitHub Actions 自动发布、用第三方监控服务检测存活状态时,一个“明确且高质量的探活路径”就变得不可或缺。
本文从常见 WordPress 页面用于健康检查的实际表现出发,,指出了它作为探活接口的一些不适之处,然后通过自定义”register_rest_route()” 注册了一个无副作用的 “/wp-json/healthmonitor/check” 路径,使其严格返回 204 No Content,没有 body,没有缓存干扰,没有歧义,完全符合现代 Web 服务中对探活接口的通用标准。
更重要的是,这种设计方式非常适合纳入自动化、边缘计算与缓存协同的整体架构之中。例如,Cloudflare APO 并不会缓存返回状态码为 204 的响应,本地缓存插件(如 WP Super Cache)也能避免误缓存这类探活页面;同时,像 curl 这样的工具也可以轻松集成使用,让 CI/CD 中的探测步骤不再依赖繁琐的 HTML 或 JSON 解析;而未来若要接入负载均衡器或容器编排平台(例如 Kubernetes 的 readinessProbe),也可以顺利衔接,无需额外适配。
当然,这种探活接口的思路主要服务于动态网站。如果你的站点已经完全静态化,甚至部署在 Cloudflare Pages 这类平台上,那就无需额外设计探活逻辑了——CDN 本身的可用性监控,已经足够应对故障检测的需求。