本文目录导读:

- 核心思路
- 方案一:基于配置文件(简单、适用单机/小项目)
- 方案二:基于数据库/Redis(灵活、支持动态配置)
- 方案三:使用任务调度 + 开关(适合整站维护)
- 高级:基于告警聚合(De-duplication + Silence)
- 最佳实践建议
- 简单封装示例(即时可用)
在 PHP 项目中实现告警静默(时段屏蔽通知),通常是为了在维护窗口、非工作时间或已知故障期间避免不必要的告警骚扰,以下是几种常见的架构设计与实现方案,你可以根据项目复杂度选择。
核心思路
- 配置中心:定义静默规则(时间范围、周期、匹配条件)。
- 过滤器/中间件:在告警触发点(发送通知前)检查规则。
- 执行:如果匹配,则丢弃告警或标记为静默。
基于配置文件(简单、适用单机/小项目)
直接在项目配置中定义静默时段,使用数组或 .env 控制。
示例配置 (config/mute.php)
return [
'enabled' => true,
'rules' => [
[
'start' => '02:00',
'end' => '05:00',
'days' => ['Mon', 'Tue', 'Wed', 'Thu', 'Fri'], // 工作日
'match' => null, // null 表示匹配所有告警,或指定告警类名
],
[
'start' => '00:00',
'end' => '23:59',
'days' => ['Sat', 'Sun'],
'match' => 'critical', // 仅静默 critical 级别的告警
],
],
];
核心检查逻辑
class AlertMuteService
{
public function shouldMute(string $alert, string $level = null): bool
{
$config = config('mute');
if (!$config['enabled']) {
return false;
}
$now = Carbon::now();
$currentDay = $now->shortDayName; // Mon, Tue...
$currentTime = $now->format('H:i');
foreach ($config['rules'] as $rule) {
// 1. 检查日期
if (!in_array($currentDay, $rule['days'] ?? [])) {
continue;
}
// 2. 检查时间区间
if ($currentTime < $rule['start'] || $currentTime > $rule['end']) {
continue;
}
// 3. 检查匹配条件
if ($rule['match'] !== null) {
if ($rule['match'] === 'critical' && $level !== 'critical') {
continue;
}
// 也可以匹配告警名称 pattern
}
return true; // 命中静默规则
}
return false;
}
}
调用时机(发送通知前)
if (app(AlertMuteService::class)->shouldMute($alert, $level)) {
logger('Alert muted during silent period');
return;
}
// 正常发送邮件/短信/企业微信...
基于数据库/Redis(灵活、支持动态配置)
适用于需要运营后台动态修改静默时段的项目。
数据表结构(MySQL 示例)
CREATE TABLE `alert_mute_rules` (
`id` int PRIMARY KEY AUTO_INCREMENT,
`name` varchar(100) COMMENT '规则名称',
`time_zone` varchar(50) DEFAULT 'Asia/Shanghai',
`start_time` time NOT NULL,
`end_time` time NOT NULL,
`days_of_week` varchar(20) COMMENT '1-7,逗号分隔,如1,2,3,4,5',
`alert_type` varchar(50) DEFAULT NULL COMMENT 'null表示全部',
`alert_level` varchar(20) DEFAULT NULL COMMENT 'critical/warning/info',
`status` tinyint DEFAULT 1,
`created_at` timestamp
);
Redis 缓存预热(推荐)
- 将所有活跃规则保存到 Redis
Sorted Set或Hash中。 - 定时任务 (Cron) 每分钟检查当前时间是否命中规则。
- 或在发送告警时实时查询。
实时查询示例
class RedisAlertMuteChecker
{
public function isMuted($alert): bool
{
$now = new DateTime('now', new DateTimeZone('Asia/Shanghai'));
$time = $now->format('H:i');
$dayOfWeek = $now->format('N'); // 1-7
// 从 Redis 获取所有规则(建议用 Hash 存储,field为规则ID)
$rules = Redis::hGetAll('alert:mute:rules');
foreach ($rules as $rule) {
// 解析 JSON
$ruleData = json_decode($rule, true);
if (!$ruleData['status']) continue;
// 检查日期
$days = explode(',', $ruleData['days_of_week']);
if (!in_array($dayOfWeek, $days)) continue;
// 检查时间区间(支持跨天,需要特殊处理)
if ($time >= $ruleData['start_time'] && $time <= $ruleData['end_time']) {
// 匹配告警类型/级别
if ($ruleData['alert_type'] && $ruleData['alert_type'] !== $alert['type']) continue;
if ($ruleData['alert_level'] && $ruleData['alert_level'] !== $alert['level']) continue;
return true;
}
}
return false;
}
}
使用任务调度 + 开关(适合整站维护)
在项目本身进行“维护模式”时,同步静默所有告警。
方法:利用 Laravel 的 DownForMaintenance 或者项目自定义的全局变量。
if (app()->isDownForMaintenance()) {
// 直接返回,不发送任何通知
logger('Site under maintenance, alert muted');
return;
}
配合定时任务:
# 凌晨 2点进入静默 0 2 * * * php artisan mute:on --reason="系统维护" # 凌晨 5点恢复通知 0 5 * * * php artisan mute:off
高级:基于告警聚合(De-duplication + Silence)
如果使用 Prometheus + AlertManager 或 Grafana OnCall,在应用层之外还能做:
| 组件 | 静默功能 |
|---|---|
| AlertManager | 天然的 silences API,支持时间、标签匹配,php 应用只需发送告警到 AlertManager,静默由 AlertManager 维护。 |
| Grafana OnCall | 动态将告警静默、通知对接 |
| PHP + Webhook + CRON | 编写 shell 脚本定时调用 curl -XPOST alertmanager/silences |
最佳实践建议
- 不要在生产代码里 hardcode 时间:使用配置中心或数据库。
- 考虑时区:如果项目部署在全球,统一使用 UTC 存储,展示时转本地。
- 日志记录:静默的告警也要记录日志,方便事后排查。
- 跨天支持:
23:00 - 01:00的静默需要特殊逻辑。 - 优先级:如果存在多条规则,明确静默规则的优先级(如:更具体的规则优先级更高)。
简单封装示例(即时可用)
// services/AlertMuteService.php
class AlertMuteService
{
public function check(array $alert): bool
{
$config = config('alert.mute_rules', []);
$now = Carbon::now();
foreach ($config as $rule) {
// 解析时间
$start = Carbon::parse($rule['start']);
$end = Carbon::parse($rule['end']);
// 处理跨天
if ($start->greaterThan($end)) {
// 跨越午夜,如 23:00 -> 01:00
if (!($now->greaterThanOrEqualTo($start) || $now->lessThanOrEqualTo($end))) {
continue;
}
} else {
// 普通区间
if (!($now->between($start, $end))) {
continue;
}
}
// 检查星期
if (isset($rule['days']) && !in_array($now->dayOfWeek, $rule['days'])) continue;
// 检查告警级别
if (isset($rule['level']) && $rule['level'] !== $alert['level']) continue;
return true;
}
return false;
}
}
选择哪种方案取决于你的项目规模、告警系统架构、团队对运维的可控需求,推荐至少做到 配置化 + 数据库支持动态调整,便于快速响应线上变更。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播