本文目录导读:

- 方案一:服务器层面系统监控 + 通知脚本(最简单直接)
- 方案二:使用现成开源监控系统(如 Prometheus + Alertmanager)
- 方案三:使用商业 APM / 监控平台(如 Sentry、New Relic、Datadog)
- 方案四:结合 PHP 进程级监控(如需定位具体服务)
- 总结:推荐组合方案(成熟且成本低)
针对 PHP 项目 CPU 负载过高触发告警通知,可以构建一个监控 → 指标采集 → 阈值判定 → 告警通知的闭环体系,以下是几种常用且有效的方案,从简单到复杂排列:
服务器层面系统监控 + 通知脚本(最简单直接)
适用场景:没有复杂监控系统,想快速实现告警。
编写 Shell 脚本检测 CPU 负载
在服务器上创建一个脚本 /usr/local/bin/cpu_alert.sh:
#!/bin/bash
# CPU负载阈值 (可根据核心数调整,CPU核心数*1.5)
LOAD_THRESHOLD=2.0
# 通知间隔(秒),防止频繁告警
NOTIFY_INTERVAL=300
# 当前 1分钟平均负载
CURRENT_LOAD=$(uptime | awk -F'load average:' '{print $2}' | awk -F',' '{print $1}' | sed 's/ //g')
# 负载对比(浮点数比较)
if (( $(echo "$CURRENT_LOAD > $LOAD_THRESHOLD" | bc -l) )); then
# 检查上次通知时间,避免重复告警
LAST_NOTIFY_FILE="/tmp/cpu_alert_last_notify"
CURRENT_TIME=$(date +%s)
if [ -f "$LAST_NOTIFY_FILE" ]; then
LAST_NOTIFY=$(cat "$LAST_NOTIFY_FILE")
TIME_DIFF=$(( CURRENT_TIME - LAST_NOTIFY ))
else
TIME_DIFF=$NOTIFY_INTERVAL # 首次触发
fi
if [ $TIME_DIFF -ge $NOTIFY_INTERVAL ]; then
# 发送通知(示例:钉钉、企业微信、飞书、邮件等)
MESSAGE="[告警] 服务器 $(hostname) CPU负载过高,当前负载: $CURRENT_LOAD (阈值: $LOAD_THRESHOLD)"
# 示例:调用外部Webhook (钉钉机器人)
curl -s -X POST "https://oapi.dingtalk.com/robot/send?access_token=YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d "{\"msgtype\":\"text\",\"text\":{\"content\":\"$MESSAGE\"}}" > /dev/null 2>&1
# 记录通知时间
echo "$CURRENT_TIME" > "$LAST_NOTIFY_FILE"
fi
fi
设置 Crontab 定时执行
# 每分钟检查一次 * * * * * /bin/bash /usr/local/bin/cpu_alert.sh
优点:极简、不依赖第三方平台。
缺点:只能监控服务器整体负载,无法关联 PHP 进程(比如是哪个PHP-FPM池或者哪个Web服务引起的)。
使用现成开源监控系统(如 Prometheus + Alertmanager)
适用场景:多台服务器、需要历史数据和可视化、想统一管理告警。
部署架构
服务器 (Node Exporter) → Prometheus (采集和存储) → Alertmanager (告警管理) → 通知渠道
关键配置示例
Prometheus 告警规则 (cpu_alert.yml):
groups:
- name: cpu_alerts
rules:
- alert: HighCpuLoad
expr: node_load1 > (count(node_cpu_seconds_total{mode="idle"}) * 1.5)
for: 2m
labels:
severity: warning
annotations:
summary: "服务器 {{ $labels.instance }} CPU负载过高"
description: "当前负载: {{ $value }} (历史平均值)"
Alertmanager 通知配置(以钉钉为例):
receivers:
- name: 'webhook'
webhook_configs:
- url: 'https://oapi.dingtalk.com/robot/send?access_token=YOUR_TOKEN'
send_resolved: true
优点:功能全面、可扩展、支持多维度告警。
缺点:需要部署和维护 Prometheus 生态,学习成本略高。
使用商业 APM / 监控平台(如 Sentry、New Relic、Datadog)
适用场景:已有商业监控预算,或需要深度应用性能监控。
- Datadog:
monitor "avg:system.cpu.user{*}" > 80,可直接对接 Slack、PagerDuty。 - Sentry:可以监控 PHP 慢事务和高 CPU 消耗的异常。
- 阿里云 / 腾讯云云监控:如果服务器在云上,直接使用云厂商的告警服务(如云监控 + 云函数 + 短信/电话通知)。
优点:开箱即用,免运维,功能强大。
缺点:费用较高,数据可能出网。
结合 PHP 进程级监控(如需定位具体服务)
如果想知道是哪个 PHP 服务(网站、队列、定时任务)导致 CPU 过高,需要在方案一二的基础上增加进程级别监控。
示例:监控具体 PHP-FPM pool 的 CPU 使用
# 获取特定 pool 的进程CPU总和
ps aux | grep 'php-fpm: pool www' | awk '{sum+=$3} END {print sum}'
告警脚本逻辑:
- 整体负载高 → 进入排查流程
- 再计算
php-fpm: pool worker的 CPU 总和 → 如果占比超过 60% → 通知“Worker 池消耗高” - 或解析
strace/top定位慢请求
更专业的做法:使用 (int) sys_getloadavg()[0] 在 PHP 代码内部做熔断或降级,并在业务层触发告警(例如记录日志、调用 Webhook)。
推荐组合方案(成熟且成本低)
| 层 | 方案 | 工具 |
|---|---|---|
| 基础监控 | Shell 脚本 + Crontab(方案一) | 守护进程 |
| 进程定位 | 脚本分析 php-fpm pool 或单个 PHP worker | ps, top, strace |
| 告警渠道 | Webhook 到钉钉/企业微信/Slack | curl + Webhook URL |
最佳实践步骤:
- 先用方案一快速实现告警(1小时搞定)
- 后期如果服务器增多,迁移到方案二(Prometheus)
- 如果业务需要精细到每个接口的 CPU 消耗,再上方案三或 APM
这样既能快速响应问题,又不至于一开始就引入过重的架构。