Laravel健康检查最佳实践:从零搭建高可用监控系统
📖 目录导读
- 什么是Laravel健康检查?为什么需要它?
- 主流方案对比:spatie/laravel-health vs Laravel内置方案
- 实战部署:从安装到自定义检查器
- 关键指标监控:数据库、缓存、队列、磁盘
- 可视化与告警集成:让健康检查“看得见、传得出”
- 常见问题与排坑指南(含问答)
- 安全加固与生产环境注意事项
什么是Laravel健康检查?为什么需要它?
Laravel健康检查(Health Check) 是一套系统自检机制,通过定期执行一系列检查项(如数据库连通性、缓存服务状态、磁盘空间、队列工作者存活等),来评估应用当前是否正常运行。

为什么需要它?
- 提前发现故障:在用户报错前,自动检测到Redis宕机、MySQL连接池耗尽等隐患
- 辅助自动化运维:Kubernetes的Readiness Probe、AWS的ELB健康检查都需要HTTP端点响应
- 满足SLA监控:生产环境中必须对外暴露
/health接口,供负载均衡器或监控系统(如Prometheus、Datadog)调用
问答:健康检查跟日志监控有什么区别? A:日志监控是事后追溯,发现错误时问题已发生;健康检查是实时探测,在服务完全崩溃前发出预警,两者互补,不可替代。
主流方案对比:spatie/laravel-health vs Laravel内置方案
方案A:spatie/laravel-health(推荐)
| 特性 | 说明 |
|---|---|
| 安装方式 | composer require spatie/laravel-health |
| 检查项 | 内置数据库、Redis、队列、SSL证书、磁盘、Memcached等20+检查器 |
| 扩展性 | 可自定义检查器,支持异步检查(避免阻塞) |
| 可视化 | 自带美观的仪表盘(辐射图/柱状图) |
| 结果格式 | JSON(供API) + 仪表盘视图(供人类) |
方案B:Laravel内置路由+手动检查
Route::get('/health', function () {
try {
DB::connection()->getPdo(); // 数据库检查
return response()->json(['status' => 'ok']);
} catch (\Exception $e) {
return response()->json(['status' => 'fail'], 500);
}
});
缺点:代码零散、无标准化、无缓存/队列检查、无聚合数据。
生产环境建议使用spatie/laravel-health,它已是Laravel生态中最成熟、最广泛使用的健康检查包(GitHub 2.5k+ Star)。
实战部署:从安装到自定义检查器
步骤1:安装与发布配置文件
composer require spatie/laravel-health php artisan vendor:publish --provider="Spatie\Health\HealthServiceProvider" --tag="health-config" php artisan vendor:publish --provider="Spatie\Health\HealthServiceProvider" --tag="health-migrations" php artisan migrate
步骤2:注册检查项(config/health.php)
return [
'checks' => [
\Spatie\Health\Checks\Checks\DatabaseCheck::class,
\Spatie\Health\Checks\Checks\RedisCheck::class,
\Spatie\Health\Checks\Checks\CacheCheck::class,
\Spatie\Health\Checks\Checks\DiskSpaceCheck::class->warningStorage(80)->errorStorage(90),
],
'result_stores' => [
\Spatie\Health\ResultStores\EloquentHealthResultStore::class,
],
];
步骤3:添加路由与仪表盘
// routes/web.php
Route::health('/health');
访问http://your-domain/health即可看到JSON格式的健康报告;
访问/health/dashboard可查看可视化仪表盘。
步骤4:快速验证
curl http://localhost/health
# 返回示例:
# {
# "status": "ok",
# "checked_at": "2027-03-25T10:00:00Z",
# "checks": [
# {"name": "Database", "status": "ok", "message": "Connection successful"},
# {"name": "Redis", "status": "ok"},
# ...
# ]
# }
问答:如何检查队列工作者(Queue Worker)是否存活? A:使用
QueueCheck类,它会检测是否有活跃的队列进程在监听指定队列,配置示例:\Spatie\Health\Checks\Checks\QueueCheck::new() ->onQueue('default') ->failWhenQueueIsEmpty(false) // 允许空队列不报错
关键指标监控:数据库、缓存、队列、磁盘
数据库检查
// 默认检查连接是否正常,可自定义超时
DatabaseCheck::new()->connectionName('mysql')->timeout(5)
缓存检查
// 检测缓存驱动(Redis/Memcached/File)能否正常读写
CacheCheck::new()->driver('redis')->expectedTtl(60)
磁盘空间
DiskSpaceCheck::new()
->warningWhenPercentageUsedIsAbove(75) // 磁盘使用>75%触发警告
->failWhenPercentageUsedIsAbove(90) // >90%触发故障
SSL证书有效期
SslCertificateCheck::new()
->url('https://your-domain.com')
->failWhenCertificateExpiringInDays(14) // 证书14天内过期则告警
邮件发送服务
// 需自定义检查器,检测SMTP连接
class MailCheck extends \Spatie\Health\Checks\Check
{
public function run(): CheckResult
{
try {
Mail::raw('test', fn($msg) => $msg->to('test@example.com'));
return CheckResult::ok();
} catch (\Exception $e) {
return CheckResult::failed()->comment($e->getMessage());
}
}
}
可视化与告警集成:让健康检查“看得见、传得出”
内置仪表盘
访问/health/dashboard,以辐射图、进度条等方式展示所有检查项状态。
支持设置定时自动刷新(每30秒一次)。
集成Slack/钉钉/邮件告警
利用Laravel的通知系统:
// config/health.php
'notifications' => [
\Spatie\Health\Notifications\CheckFailedNotification::class => [
'mail' => ['admin@your-company.com'],
'slack' => [
'webhook_url' => env('SLACK_HEALTH_WEBHOOK'),
],
],
],
对接Prometheus
安装扩展包:composer require spatie/laravel-health-prometheus
然后暴露/health/prometheus端点,供Grafana抓取并绘制指标。
常见问题与排坑指南(含问答)
Q1:健康检查频繁超时,影响正常请求怎么办?
A:启用异步检查,将config/health.php中的queue_runner设为true:
'queue_runner' => [
'enabled' => true,
'queue' => 'default',
'connection' => 'redis',
],
检查任务会排队异步执行,不阻塞HTTP响应。
Q2:如何排除某些路由?比如健康检查数据不想被外部访问?
A:结合Laravel的中间件或IP白名单:
Route::middleware(['auth.basic', 'throttle:60,1'])->health('/health');
或通过配置config/health.php的middleware数组。
Q3:DiskSpaceCheck在Linux容器中报告错误的磁盘使用率?
A:因为容器内df命令看到的往往是宿主机文件系统,解决方案:
- 使用
->filesystem('/app')指定要监控的目录路径 - 或者自定义检查器调用
disk_free_space('/app')函数
Q4:如何检查某个外部API是否可访问?
A:创建自定义检查器:
class ExternalApiCheck extends Check
{
protected string $url = 'https://third-party.com/api/ping';
public function run(): CheckResult
{
$response = Http::timeout(5)->get($this->url);
return $response->successful()
? CheckResult::ok()
: CheckResult::failed("Status code: " . $response->status());
}
}
Q5:数据库连接检查正常,但业务SQL报错,怎么发现?
A:健康检查是“浅层检测”,只能验证连接性,深层业务错误需结合应用性能监控(APM),如Sentry、New Relic。
安全加固与生产环境注意事项
- 隐藏仪表盘:仅允许内网IP访问
/health/dashboard,生产环境可通过php artisan down维护时禁用仪表盘。 - 请求频率限制:对健康检查端点添加
throttle中间件,防止恶意刷请求。 - 敏感信息保护:自定义检查器中避免输出数据库密码、Redis密码等敏感信息。
- 多环境适配:本地环境可开启全部检查,生产环境建议只保留核心检查项(数据库、Redis、磁盘)。
- 结果持久化:启用
EloquentHealthResultStore,将历史检查数据存入数据库,便于趋势分析。
一个生产级的Laravel健康检查应该具备实时性、全面性、可扩展性,通过spatie/laravel-health,你可以在10分钟内完成部署,后续通过自定义检查器覆盖业务特有需求,再结合告警系统形成完整的“发现-通知-响应”闭环,健康检查不是“做完一次就完事”,而是需要持续维护检查项、调整阈值,让它随着业务演进不断优化。