本文目录导读:

在PHP项目中实现短信告警主要有三种方式,我按照推荐程度和适用场景为你详细介绍:
使用第三方短信服务商(最推荐)
主流服务商对比
| 服务商 | 特点 | 价格参考 |
|---|---|---|
| 阿里云短信 | 国内最成熟,覆盖广 | 约0.045元/条 |
| 腾讯云短信 | 与微信生态整合好 | 约0.05元/条 |
| Twilio | 国际业务首选 | 约$0.0079/条 |
阿里云短信实现示例
<?php
// 1. 安装依赖
// composer require alibabacloud/dysmsapi-20170525
use AlibabaCloud\Client\AlibabaCloud;
use AlibabaCloud\Client\Exception\ClientException;
use AlibabaCloud\Client\Exception\ServerException;
class SmsAlert
{
private $accessKeyId;
private $accessKeySecret;
private $signName; // 短信签名
public function __construct()
{
$this->accessKeyId = '你的AccessKeyId';
$this->accessKeySecret = '你的AccessKeySecret';
$this->signName = '你的签名';
}
/**
* 发送短信告警
*/
public function sendAlert(string $phone, string $message): bool
{
try {
AlibabaCloud::accessKeyClient(
$this->accessKeyId,
$this->accessKeySecret
)->regionId('cn-hangzhou')->asDefaultClient();
$result = AlibabaCloud::rpc()
->product('Dysmsapi')
->version('2017-05-25')
->action('SendSms')
->method('POST')
->host('dysmsapi.aliyuncs.com')
->options([
'query' => [
'PhoneNumbers' => $phone,
'SignName' => $this->signName,
'TemplateCode' => 'SMS_XXXXXXXX', // 短信模板ID
'TemplateParam' => json_encode([
'content' => $message
]),
],
])
->request();
$response = $result->toArray();
if ($response['Code'] === 'OK') {
return true;
}
throw new \Exception("短信发送失败: " . $response['Message']);
} catch (ClientException $e) {
throw new \Exception("客户端错误: " . $e->getErrorMessage());
} catch (ServerException $e) {
throw new \Exception("服务端错误: " . $e->getErrorMessage());
}
}
}
// 使用示例
$sms = new SmsAlert();
try {
$sms->sendAlert('13800138000', '服务器CPU使用率超过90%,请及时处理');
} catch (\Exception $e) {
// 记录日志
error_log($e->getMessage());
}
通过HTTP API接口(通用方案)
<?php
class HttpSmsAlert
{
private $apiUrl;
private $apiKey;
public function __construct()
{
// 以某第三方接口为例
$this->apiUrl = 'https://api.smsprovider.com/send';
$this->apiKey = 'YOUR_API_KEY';
}
public function sendSms(string $phone, string $content): bool
{
$data = [
'phone' => $phone,
'content' => $content,
'apikey' => $this->apiKey,
];
// 使用cURL发送请求
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $this->apiUrl);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data));
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);
if ($httpCode === 200) {
$result = json_decode($response, true);
return $result['status'] === 'success';
}
return false;
}
}
集成消息队列实现异步告警
<?php
// 使用Redis作为消息队列
class AsyncSmsAlert
{
private $redis;
private $smsService;
public function __construct()
{
$this->redis = new Redis();
$this->redis->connect('127.0.0.1', 6379);
$this->smsService = new SmsAlert(); // 使用上面的阿里云类
}
/**
* 添加告警任务到队列
*/
public function addAlertTask(string $phone, string $message): void
{
$task = [
'phone' => $phone,
'message' => $message,
'time' => time(),
];
$this->redis->lPush('sms_alert_queue', json_encode($task));
}
/**
* 消费队列中的告警任务(在后台进程中运行)
*/
public function consumeAlertQueue(): void
{
while (true) {
$task = $this->redis->brPop('sms_alert_queue', 5);
if ($task) {
$data = json_decode($task[1], true);
try {
$this->smsService->sendAlert(
$data['phone'],
$data['message']
);
// 记录发送日志
$this->logAlert($data);
} catch (\Exception $e) {
// 发送失败,重新入队或记录错误
$this->redis->lPush('sms_alert_failed', $task[1]);
error_log("短信发送失败: " . $e->getMessage());
}
}
}
}
private function logAlert(array $data): void
{
$log = sprintf(
"[%s] 发送告警到 %s: %s\n",
date('Y-m-d H:i:s'),
$data['phone'],
$data['message']
);
file_put_contents('/var/log/sms_alert.log', $log, FILE_APPEND);
}
}
完整告警系统示例
<?php
class AlertManager
{
private $smsService;
private $alertRules = [];
private $recipients = [];
public function __construct()
{
$this->smsService = new SmsAlert();
$this->initConfig();
}
/**
* 初始化配置
*/
private function initConfig(): void
{
// 告警规则
$this->alertRules = [
'cpu_high' => [
'threshold' => 90,
'message' => 'CPU使用率已超过90%',
],
'memory_low' => [
'threshold' => 500, // MB
'message' => '可用内存低于500MB',
],
'disk_full' => [
'threshold' => 90,
'message' => '磁盘使用率超过90%',
],
];
// 接收人
$this->recipients = [
'13800138000',
'13900139000',
];
}
/**
* 检查系统状态并发送告警
*/
public function checkAndAlert(): void
{
$alerts = [];
// 检查CPU
$cpuUsage = $this->getCpuUsage();
if ($cpuUsage > $this->alertRules['cpu_high']['threshold']) {
$alerts[] = $this->alertRules['cpu_high']['message'] .
" (当前: {$cpuUsage}%)";
}
// 检查内存
$memoryFree = $this->getFreeMemory();
if ($memoryFree < $this->alertRules['memory_low']['threshold']) {
$alerts[] = $this->alertRules['memory_low']['message'] .
" (当前: {$memoryFree}MB)";
}
// 检查磁盘
$diskUsage = $this->getDiskUsage();
if ($diskUsage > $this->alertRules['disk_full']['threshold']) {
$alerts[] = $this->alertRules['disk_full']['message'] .
" (当前: {$diskUsage}%)";
}
// 发送告警
if (!empty($alerts)) {
$message = implode("\n", $alerts);
foreach ($this->recipients as $phone) {
try {
$this->smsService->sendAlert($phone, $message);
} catch (\Exception $e) {
error_log("发送到 {$phone} 失败: " . $e->getMessage());
}
}
}
}
private function getCpuUsage(): float
{
$load = sys_getloadavg();
return $load[0] * 100; // 转换为百分比
}
private function getFreeMemory(): float
{
if (PHP_OS_FAMILY === 'Linux') {
$free = shell_exec("free -m | awk 'NR==2{print $4}'");
return (float) trim($free);
}
return 1000; // Windows下返回默认值
}
private function getDiskUsage(): float
{
$total = disk_total_space("/");
$free = disk_free_space("/");
if ($total > 0) {
return (($total - $free) / $total) * 100;
}
return 0;
}
}
// 使用示例
$alertManager = new AlertManager();
// 可以放在cron中定时执行
// * * * * * php /path/to/alert.php
$alertManager->checkAndAlert();
// 或者在特定事件触发时调用
$alertManager->addAlertTask('13800138000', '用户XXX进行了敏感操作');
最佳实践建议
配置管理
// 使用.env文件管理敏感信息
// composer require vlucas/phpdotenv
$dotenv = Dotenv\Dotenv::createImmutable(__DIR__);
$dotenv->load();
define('SMS_ACCESS_KEY', $_ENV['SMS_ACCESS_KEY']);
define('SMS_SECRET_KEY', $_ENV['SMS_SECRET_KEY']);
限流和频率控制
class RateLimiter
{
private $redis;
public function __construct()
{
$this->redis = new Redis();
$this->redis->connect('127.0.0.1', 6379);
}
public function checkRateLimit(string $phone): bool
{
$key = "sms_limit:{$phone}:" . date('H');
$count = $this->redis->incr($key);
if ($count === 1) {
$this->redis->expire($key, 3600);
}
// 每小时最多5条
return $count <= 5;
}
}
日志和监控
// 记录所有发送记录
class SmsLogger
{
public static function log(string $phone, string $message, bool $success): void
{
$logData = [
'time' => date('Y-m-d H:i:s'),
'phone' => $phone,
'message' => $message,
'success' => $success,
];
file_put_contents(
'/var/log/sms_history.log',
json_encode($logData) . PHP_EOL,
FILE_APPEND
);
}
}
多通道切换
// 主服务商失败时切换到备用
class SmsMultiChannel
{
private $channels = [];
private $currentChannel = 0;
public function sendSms(string $phone, string $message): bool
{
for ($i = 0; $i < count($this->channels); $i++) {
try {
$result = $this->channels[$i]->send($phone, $message);
if ($result) {
return true;
}
} catch (\Exception $e) {
continue;
}
}
return false;
}
}
- 小项目:直接使用阿里云/腾讯云短信SDK
- 中型项目:加入消息队列实现异步处理
- 大型项目:构建完整的告警系统,包括限流、日志、多通道
建议从阿里云短信开始实现,它提供完善的API和文档,成本也比较低,记得在生产环境中使用异步方式发送,避免阻塞主流程。
版权声明:足球直播
足球直播
足球直播
足球直播
足球直播
中超直播
中超直播
中超直播
中超直播
中超直播
英超直播
英超直播
英超直播
英超直播
英超直播
德甲直播
德甲直播
德甲直播
德甲直播
德甲直播
西甲直播
西甲直播
西甲直播
西甲直播
西甲直播
意甲直播
意甲直播
意甲直播
意甲直播
意甲直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
足球直播
足球直播
足球直播
足球直播
足球直播
中超直播
中超直播
中超直播
中超直播
中超直播
英超直播
英超直播
英超直播
英超直播
英超直播
德甲直播
德甲直播
德甲直播
德甲直播
德甲直播
西甲直播
西甲直播
西甲直播
西甲直播
西甲直播
意甲直播
意甲直播
意甲直播
意甲直播
意甲直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
足球直播
足球直播
足球直播
足球直播
足球直播
中超直播
中超直播
中超直播
中超直播
中超直播
英超直播
英超直播
英超直播
英超直播
英超直播
德甲直播
德甲直播
德甲直播
德甲直播
德甲直播
西甲直播
西甲直播
西甲直播
西甲直播
西甲直播
意甲直播
意甲直播
意甲直播
意甲直播
意甲直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播