SiteReliabilityState 是运行时计算的复合业务状态,需用独立类封装而非 Eloquent 访问器;它依赖多源监控信号(延迟、错误率、队列深度、上游健康),应由上层服务组装实例并显式注入响应。
PHP 中 Eloquent 模型无法直接定义“站点可靠性状态(SRE-style)”这类复合业务属性——它不是字段映射,而是运行时计算+可观测性协同的结果,必须手动封装逻辑、避免污染模型职责。
什么是
属性?别当普通访问器用
这不是一个数据库字段,也不是
能解决的场景。典型 SRE 状态(如
/
/
)依赖多个信号源:API 延迟 P95、错误率、上游服务连通性、队列积压量。Eloquent 的访问器只适合单字段派生,强行塞进
会导致:
每次访问都触发多次外部调用(HTTP、Redis、DB),严重拖慢响应
无法缓存或批量预加载,和 Laravel 的 eager loading 机制冲突
测试困难——你得 mock 整个监控栈才能测一个
用
类解耦状态计算逻辑
把状态判定抽成独立类,让 Eloquent 模型只负责数据,不负责 SRE 决策。例如:
这样做的好处:
立即学习
“
PHP免费学习笔记(深入)
”;
PHP 8.5.5
PHP 8.5.5 是 PHP 8.5 分支的维护更新版本。该版本延续了“小步快跑”的迭代逻辑,通过深度错误修复、底层性能微调以及安全加固,旨在为开发者提供一个更健壮、更高效的运行环境。该版本严格遵守语义化版本规范,不包含破坏性变更。
下载
可单元测试:传入不同参数组合,断言返回值
可复用:同一个实例能用于 API 响应、Prometheus 指标采集、告警判断
和 Eloquent 解耦:模型里不出现
或
在控制器或服务层组装
实例
不要在模型里调用监控指标。应该由上层决定何时、如何采集信号:
Web 请求中:从缓存(如 Redis)读取最近 60 秒的聚合指标,构造
Artisan 命令中:拉取 Prometheus 查询结果,生成状态快照并写入日志
Health Check 路由中:合并 DB 连接、Redis Ping、关键 API 探活结果
示例(Laravel 控制器):
避免把
当作模型属性序列化输出
如果在 API 响应里直接
,别指望它自动包含
。Eloquent 不会识别自定义类实例。正确做法:
显式添加到响应数组:
用 API Resource 封装:
,在 resource 中定义
字段
绝不重写
+
—— 那是在给模型埋雷
真正难的不是写几行 PHP,而是守住边界:Eloquent 是数据映射层,不是状态引擎。一旦开始在
里监听事件更新可靠性分数,或在
观察器里上报指标,就已偏离 SRE 工程实践的本质——可观测性必须可验证、可隔离、可回滚。
SiteReliabilityStategetXXXAttribute()degradedunavailablehealthygetAttributegetReliabilityStateAttribute()SiteReliabilityStateclass SiteReliabilityState
{
public function __construct(
private readonly float $p95LatencyMs,
private readonly float $errorRatePercent,
private readonly int $queueDepth,
private readonly bool $upstreamHealthy
) {}
public function value(): string
{
if (!$this->upstreamHealthy) return 'unavailable';
if ($this->errorRatePercent > 5.0 || $this->p95LatencyMs > 2000.0) return 'degraded';
if ($this->queueDepth > 1000) return 'degraded';
return 'healthy';
}
}Http::get()Redis::get()SiteReliabilityStateSiteReliabilityStatepublic function health()
{
$metrics = Cache::get('sre_metrics', [
'p95_latency_ms' => 120.5,
'error_rate_pct' => 0.8,
'queue_depth' => 42,
'upstream_healthy' => true,
]);
$state = new SiteReliabilityState(
$metrics['p95_latency_ms'],
$metrics['error_rate_pct'],
$metrics['queue_depth'],
$metrics['upstream_healthy']
);
return response()->json(['status' => $state->value()]);
}SiteReliabilityStatereturn $model->toArray()reliability_statearray_merge($model->toArray(), ['reliability_state' => $state->value()])new HealthResource($model, $state)reliability_state$appendsgetReliabilityStateAttributeboot()saved