本文目录导读:

我来详细介绍PHP项目实现告警通知的几种主流方案。
基础架构设计
告警系统核心组件
告警源 → 告警判断 → 告警队列 → 通知渠道 → 用户
代码实现方案
邮件告警(最基础)
<?php
// EmailAlert.php
class EmailAlert {
private $to;
private $subject;
private $headers;
public function __construct($to, $from = 'alert@yourdomain.com') {
$this->to = $to;
$this->headers = "From: $from\r\n";
$this->headers .= "Content-Type: text/html; charset=UTF-8\r\n";
}
public function sendAlert($level, $message, $data = []) {
$subject = "[{$level}] 系统告警通知";
$body = $this->buildEmailBody($level, $message, $data);
return mail($this->to, $subject, $body, $this->headers);
}
private function buildEmailBody($level, $message, $data) {
$html = "<h2>系统告警通知</h2>";
$html .= "<p><strong>级别:</strong> {$level}</p>";
$html .= "<p><strong>时间:</strong> " . date('Y-m-d H:i:s') . "</p>";
$html .= "<p><strong>消息:</strong> {$message}</p>";
if (!empty($data)) {
$html .= "<h3>详细信息:</h3><pre>" . json_encode($data, JSON_PRETTY_PRINT) . "</pre>";
}
return $html;
}
}
短信告警(使用阿里云SMS)
<?php
// SmsAlert.php
require_once 'vendor/autoload.php';
use AlibabaCloud\Client\AlibabaCloud;
use AlibabaCloud\Client\Exception\ClientException;
use AlibabaCloud\Client\Exception\ServerException;
class SmsAlert {
private $accessKeyId;
private $accessKeySecret;
private $signName;
private $templateCode;
public function __construct($config) {
$this->accessKeyId = $config['access_key_id'];
$this->accessKeySecret = $config['access_key_secret'];
$this->signName = $config['sign_name'];
$this->templateCode = $config['template_code'];
AlibabaCloud::accessKeyClient(
$this->accessKeyId,
$this->accessKeySecret
)->regionId('cn-hangzhou')->asDefaultClient();
}
public function sendSms($phoneNumbers, $level, $message) {
try {
$result = AlibabaCloud::rpc()
->product('Dysmsapi')
->version('2017-05-25')
->action('SendSms')
->method('POST')
->options([
'query' => [
'PhoneNumbers' => $phoneNumbers,
'SignName' => $this->signName,
'TemplateCode' => $this->templateCode,
'TemplateParam' => json_encode([
'level' => $level,
'message' => $message,
'time' => date('H:i:s')
]),
],
])
->request();
return $result->toArray();
} catch (ClientException $e) {
throw new Exception("发送短信失败: " . $e->getErrorMessage());
} catch (ServerException $e) {
throw new Exception("服务器错误: " . $e->getErrorMessage());
}
}
}
企业微信/钉钉机器人告警
<?php
// WebhookAlert.php
class WebhookAlert {
private $webhookUrl;
private $type; // 'wechat' or 'dingtalk'
public function __construct($webhookUrl, $type = 'wechat') {
$this->webhookUrl = $webhookUrl;
$this->type = $type;
}
public function sendAlert($level, $message, $data = []) {
$payload = $this->buildPayload($level, $message, $data);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $this->webhookUrl);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
return $httpCode === 200;
}
private function buildPayload($level, $message, $data) {
if ($this->type === 'dingtalk') {
return [
'msgtype' => 'markdown',
'markdown' => [
'title' => "【{$level}】系统告警通知",
'text' => "### 系统告警通知\n" .
"**级别:** {$level}\n" .
"**时间:** " . date('Y-m-d H:i:s') . "\n" .
"**消息:** {$message}\n" .
(!empty($data) ? "**详细信息:** \n```json\n" .
json_encode($data, JSON_PRETTY_PRINT) . "\n```" : "")
]
];
} else {
// 企业微信格式
$content = "[{$level}] {$message}\n时间: " . date('Y-m-d H:i:s');
return [
'msgtype' => 'text',
'text' => [
'content' => $content
]
];
}
}
}
告警管理器(统一管理)
<?php
// AlertManager.php
class AlertManager {
private $channels = [];
private $alertHistory = [];
private $throttleConfig = [];
public function addChannel($name, $channel) {
$this->channels[$name] = $channel;
$this->throttleConfig[$name] = [
'last_sent' => 0,
'count' => 0,
'max_per_minute' => 10
];
}
public function sendAlert($level, $message, $data = [], $channels = []) {
$alertId = $this->generateAlertId();
$this->alertHistory[$alertId] = [
'level' => $level,
'message' => $message,
'data' => $data,
'time' => time()
];
$results = [];
// 如果没有指定通道,发送到所有通道
if (empty($channels)) {
$channels = array_keys($this->channels);
}
foreach ($channels as $channelName) {
if (!isset($this->channels[$channelName])) {
$results[$channelName] = false;
continue;
}
// 限流检查
if (!$this->checkThrottle($channelName)) {
$results[$channelName] = false;
continue;
}
try {
$result = $this->channels[$channelName]->sendAlert(
$level,
$message,
$data
);
$results[$channelName] = $result;
// 记录发送状态
$this->logAlert($alertId, $channelName, $result);
} catch (Exception $e) {
$results[$channelName] = false;
$this->logError($channelName, $e->getMessage());
}
}
return $results;
}
private function checkThrottle($channelName) {
$currentTime = time();
$config = $this->throttleConfig[$channelName];
// 重置计数器
if ($currentTime - $config['last_sent'] >= 60) {
$this->throttleConfig[$channelName] = [
'last_sent' => $currentTime,
'count' => 0,
'max_per_minute' => $config['max_per_minute']
];
}
// 检查是否超过限制
if ($config['count'] >= $config['max_per_minute']) {
return false;
}
$this->throttleConfig[$channelName]['count']++;
return true;
}
private function generateAlertId() {
return md5(uniqid() . time() . rand());
}
private function logAlert($alertId, $channel, $success) {
$logEntry = [
'alert_id' => $alertId,
'channel' => $channel,
'success' => $success,
'time' => date('Y-m-d H:i:s')
];
// 写入日志文件
file_put_contents(
'/var/log/alert_history.log',
json_encode($logEntry) . PHP_EOL,
FILE_APPEND
);
}
private function logError($channel, $errorMessage) {
file_put_contents(
'/var/log/alert_errors.log',
date('Y-m-d H:i:s') . " - {$channel}: {$errorMessage}" . PHP_EOL,
FILE_APPEND
);
}
}
使用场景示例
<?php
// 使用示例
require_once 'AlertManager.php';
require_once 'EmailAlert.php';
require_once 'WebhookAlert.php';
// 1. 初始化告警管理器
$alertManager = new AlertManager();
// 2. 配置告警通道
$alertManager->addChannel('email', new EmailAlert('admin@example.com'));
$alertManager->addChannel('wechat', new WebhookAlert(
'https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=your-key',
'wechat'
));
$alertManager->addChannel('dingtalk', new WebhookAlert(
'https://oapi.dingtalk.com/robot/send?access_token=your-token',
'dingtalk'
));
// 3. 业务监控中的使用
class BusinessMonitor {
private $alertManager;
public function __construct($alertManager) {
$this->alertManager = $alertManager;
}
// 监控数据库连接
public function checkDatabaseConnection() {
try {
$db = new PDO('mysql:host=localhost;dbname=test', 'user', 'pass');
// 模拟连接成功
return true;
} catch (PDOException $e) {
$this->alertManager->sendAlert(
'CRITICAL',
"数据库连接失败: " . $e->getMessage(),
['host' => 'localhost', 'error_code' => $e->getCode()],
['email', 'wechat'] // 发送到指定通道
);
return false;
}
}
// 监控服务器资源
public function checkServerResources() {
$cpuUsage = sys_getloadavg()[0];
$memoryUsage = $this->getMemoryUsage();
// CPU使用率超过80%告警
if ($cpuUsage > 0.8) {
$this->alertManager->sendAlert(
'WARNING',
"CPU使用率过高: " . round($cpuUsage * 100) . "%",
['cpu_usage' => $cpuUsage, 'threshold' => 0.8],
['dingtalk']
);
}
// 内存使用率超过90%告警
if ($memoryUsage > 0.9) {
$this->alertManager->sendAlert(
'CRITICAL',
"内存使用率过高: " . round($memoryUsage * 100) . "%",
['memory_usage' => $memoryUsage, 'threshold' => 0.9],
['wechat', 'email']
);
}
}
private function getMemoryUsage() {
$free = shell_exec('free');
$free = (string)trim($free);
$freeArr = explode("\n", $free);
$mem = explode(" ", $freeArr[1]);
$mem = array_filter($mem);
$mem = array_merge($mem);
$memoryUsage = $mem[2] / $mem[1];
return $memoryUsage;
}
}
// 4. 定时任务中使用(cron)
// 创建监控实例
$monitor = new BusinessMonitor($alertManager);
// 执行监控检查
$monitor->checkDatabaseConnection();
$monitor->checkServerResources();
高级功能实现
告警聚合与去重
<?php
// AlertDeduplicator.php
class AlertDeduplicator {
private $redis;
private $window = 300; // 5分钟窗口
public function __construct($redis) {
$this->redis = $redis;
}
public function isDuplicate($alertKey, $threshold = 3) {
$key = "alert:{$alertKey}";
$count = $this->redis->incr($key);
if ($count === 1) {
$this->redis->expire($key, $this->window);
return false;
}
return $count > $threshold;
}
}
告警升级机制
<?php
// EscalationManager.php
class EscalationManager {
private $levels = [
'info' => ['email' => ['admin@example.com']],
'warning' => ['email' => ['admin@example.com', 'team@example.com']],
'critical' => [
'email' => ['admin@example.com', 'team@example.com', 'manager@example.com'],
'sms' => ['13800138000'],
'phone' => ['010-88888888']
]
];
public function escalate($alert, $currentAttempt) {
$level = $alert['level'];
// 根据尝试次数升级告警级别
if ($currentAttempt >= 3 && $level === 'warning') {
$alert['level'] = 'critical';
}
return $alert;
}
}
最佳实践建议
配置管理
// config/alert.php
return [
'channels' => [
'email' => [
'class' => EmailAlert::class,
'config' => [
'to' => ['admin@example.com', 'ops@example.com'],
'from' => 'alert@yourdomain.com'
]
],
'dingtalk' => [
'class' => WebhookAlert::class,
'config' => [
'url' => 'https://oapi.dingtalk.com/robot/send?access_token=xxx',
'type' => 'dingtalk'
]
]
],
'throttle' => [
'max_per_minute' => 10,
'dedup_window' => 300 // seconds
],
'rules' => [
'db_connection' => ['level' => 'critical', 'channels' => ['email', 'dingtalk']],
'high_cpu' => ['level' => 'warning', 'channels' => ['dingtalk']]
]
];
测试建议
// tests/AlertTest.php
class AlertTest extends PHPUnit\Framework\TestCase {
public function testAlertManager() {
$alertManager = new AlertManager();
$mockChannel = $this->createMock(EmailAlert::class);
$mockChannel->expects($this->once())
->method('sendAlert')
->willReturn(true);
$alertManager->addChannel('test', $mockChannel);
$result = $alertManager->sendAlert(
'CRITICAL',
'Test alert',
['test' => true],
['test']
);
$this->assertTrue($result['test']);
}
}
这个完整的告警系统实现了多渠道、限流、去重、升级等高级功能,你可以根据实际需求选择合适的方案进行部署。
版权声明:足球直播
足球直播
足球直播
足球直播
足球直播
中超直播
中超直播
中超直播
中超直播
中超直播
英超直播
英超直播
英超直播
英超直播
英超直播
德甲直播
德甲直播
德甲直播
德甲直播
德甲直播
西甲直播
西甲直播
西甲直播
西甲直播
西甲直播
意甲直播
意甲直播
意甲直播
意甲直播
意甲直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
足球直播
足球直播
足球直播
足球直播
足球直播
中超直播
中超直播
中超直播
中超直播
中超直播
英超直播
英超直播
英超直播
英超直播
英超直播
德甲直播
德甲直播
德甲直播
德甲直播
德甲直播
西甲直播
西甲直播
西甲直播
西甲直播
西甲直播
意甲直播
意甲直播
意甲直播
意甲直播
意甲直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
足球直播
足球直播
足球直播
足球直播
足球直播
中超直播
中超直播
中超直播
中超直播
中超直播
英超直播
英超直播
英超直播
英超直播
英超直播
德甲直播
德甲直播
德甲直播
德甲直播
德甲直播
西甲直播
西甲直播
西甲直播
西甲直播
西甲直播
意甲直播
意甲直播
意甲直播
意甲直播
意甲直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播