本文目录导读:

针对PHP项目内存使用率超标预警,可以从应用层监控、系统层监控、日志告警三个维度来设计预警方案,以下是具体的实现思路和代码示例:
应用层实时监控
在PHP代码中嵌入内存检查逻辑,当内存使用超过阈值时主动告警。
1 核心监控函数
<?php
/**
* 内存监控类
*/
class MemoryMonitor {
private $threshold; // 阈值(单位:MB)
private $alertCallback; // 告警回调函数
public function __construct($thresholdMB = 128, callable $alertCallback = null) {
$this->threshold = $thresholdMB * 1024 * 1024; // 转换为字节
$this->alertCallback = $alertCallback;
}
/**
* 检查当前内存使用
* @return bool 是否超标
*/
public function checkMemoryUsage() {
$usage = memory_get_usage(true); // 获取实际分配的内存
if ($usage > $this->threshold) {
$this->triggerAlert($usage);
return true;
}
return false;
}
/**
* 触发告警
*/
private function triggerAlert($usage) {
$message = sprintf(
"[MEMORY ALERT] 内存使用超标: %.2f MB (阈值: %.2f MB)\n",
$usage / 1024 / 1024,
$this->threshold / 1024 / 1024
);
// 1. 记录日志
error_log($message);
// 2. 调用自定义告警回调
if ($this->alertCallback) {
call_user_func($this->alertCallback, $usage, $this->threshold);
}
// 3. 发送通知(示例:邮件/钉钉/企业微信)
$this->sendNotification($message);
}
/**
* 发送告警通知(以钉钉Webhook为例)
*/
private function sendNotification($message) {
$webhookUrl = 'https://oapi.dingtalk.com/robot/send?access_token=YOUR_TOKEN';
$data = [
'msgtype' => 'text',
'text' => [
'content' => $message
]
];
$ch = curl_init($webhookUrl);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_exec($ch);
curl_close($ch);
}
}
// 使用示例
$monitor = new MemoryMonitor(256, function($usage, $threshold) {
// 自定义告警逻辑:例如写入Redis、更新数据库
$redis = new Redis();
$redis->connect('127.0.0.1', 6379);
$redis->lPush('memory_alerts', json_encode([
'time' => date('Y-m-d H:i:s'),
'usage' => $usage,
'threshold' => $threshold
]));
});
// 在关键代码段执行内存检查
$monitor->checkMemoryUsage();
2 自动监控中间件(适用于框架)
以Laravel为例,创建中间件自动监控每个请求的内存使用:
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
class MemoryMonitorMiddleware
{
public function handle(Request $request, Closure $next)
{
$response = $next($request);
// 请求结束后检查内存
$peakMemory = memory_get_peak_usage(true);
$threshold = 128 * 1024 * 1024; // 128MB
if ($peakMemory > $threshold) {
\Log::warning('请求内存超标', [
'url' => $request->fullUrl(),
'memory' => $peakMemory / 1024 / 1024 . 'MB',
'method' => $request->method()
]);
// 发送告警
// ...
}
return $response;
}
}
系统层监控
1 使用shell脚本监控所有PHP进程
#!/bin/bash
# php_memory_monitor.sh
# 配置
THRESHOLD_MB=256
LOG_FILE="/var/log/php_memory_alerts.log"
WEBHOOK_URL="https://oapi.dingtalk.com/robot/send?access_token=YOUR_TOKEN"
# 获取所有PHP进程的内存使用
php_pids=$(pgrep -f "php-fpm|php-cgi|php-cli")
for pid in $php_pids; do
if [ -d "/proc/$pid" ]; then
# 获取内存使用(单位:KB)
memory_kb=$(awk '/VmRSS/{print $2}' /proc/$pid/status 2>/dev/null)
if [ ! -z "$memory_kb" ]; then
memory_mb=$((memory_kb / 1024))
if [ $memory_mb -gt $THRESHOLD_MB ]; then
# 获取进程详细信息
cmdline=$(cat /proc/$pid/cmdline 2>/dev/null | tr '\0' ' ')
message="[MEMORY ALERT] PID: $pid, 内存: ${memory_mb}MB, 命令: $cmdline"
# 记录日志
echo "$(date '+%Y-%m-%d %H:%M:%S') $message" >> $LOG_FILE
# 发送告警
curl -s -X POST -H "Content-Type: application/json" \
-d "{\"msgtype\":\"text\",\"text\":{\"content\":\"$message\"}}" \
$WEBHOOK_URL &
fi
fi
fi
done
设置cron定时任务(每分钟检查):
* * * * * /usr/local/bin/php_memory_monitor.sh
2 使用Prometheus + Grafana监控
创建自定义exporter暴露PHP内存数据:
<?php
// metrics.php - 供Prometheus抓取的指标
header('Content-Type: text/plain; charset=utf-8');
$metrics = [];
// 当前内存使用
$currentMemory = memory_get_usage(true);
$peakMemory = memory_get_peak_usage(true);
$metrics[] = "# HELP php_memory_bytes Current PHP memory usage in bytes";
$metrics[] = "# TYPE php_memory_bytes gauge";
$metrics[] = "php_memory_bytes{type=\"current\"} $currentMemory";
$metrics[] = "php_memory_bytes{type=\"peak\"} $peakMemory";
// 输出指标
echo implode("\n", $metrics) . "\n";
Prometheus告警规则:
groups:
- name: php_memory_alerts
rules:
- alert: PHPHighMemoryUsage
expr: php_memory_bytes{type="current"} > 256000000
for: 1m
labels:
severity: warning
annotations:
summary: "PHP内存使用超标"
description: "当前内存使用 {{ $value | humanize }},超过阈值 256MB"
日志告警方案
1 使用ELK+Watcher进行日志告警
- 在PHP中记录内存告警日志:
<?php // 日志格式:JSON格式便于解析 $logData = [ 'type' => 'memory_alert', 'timestamp' => date('Y-m-d\TH:i:s\Z'), 'memory_usage' => memory_get_usage(true), 'peak_memory' => memory_get_peak_usage(true), 'script' => $_SERVER['SCRIPT_NAME'] ?? 'unknown', 'pid' => getmypid() ];
error_log(json_encode($logData) . "\n", 3, '/var/log/php_memory.json.log');
2. 配置Logstash解析日志,发送到Elasticsearch
3. 在Kibana中创建Watcher告警:
```json
{
"trigger": {
"schedule": {
"interval": "1m"
}
},
"input": {
"search": {
"request": {
"indices": ["php-logs-*"],
"body": {
"query": {
"bool": {
"filter": [
{"term": {"type": "memory_alert"}},
{"range": {"memory_usage": {"gte": 268435456}}}
]
}
}
}
}
}
},
"actions": {
"email_admin": {
"email": {
"to": "admin@example.com",
"subject": "PHP内存超标告警",
"body": "发现 {{ctx.payload.hits.total}} 条内存超标记录"
}
}
}
}
完善预警体系建议
1 多级阈值设置
| 级别 | 阈值 | 处理方式 |
|---|---|---|
| WARNING | 80%阈值 | 仅记录日志 |
| CRITICAL | 100%阈值 | 发送告警通知 |
| EMERGENCY | 150%阈值 | 自动重启进程 |
2 告警渠道整合
<?php
class AlertManager {
private $channels = [];
public function addChannel($name, callable $handler) {
$this->channels[$name] = $handler;
}
public function sendAlert($level, $message, $context = []) {
foreach ($this->channels as $name => $handler) {
try {
$handler($level, $message, $context);
} catch (\Exception $e) {
error_log("告警渠道 {$name} 发送失败: " . $e->getMessage());
}
}
}
}
// 使用示例
$alertManager = new AlertManager();
$alertManager->addChannel('email', function($level, $msg, $ctx) {
// 发送邮件
});
$alertManager->addChannel('wechat', function($level, $msg, $ctx) {
// 发送企业微信
});
$alertManager->addChannel('sms', function($level, $msg, $ctx) {
// 发送短信(仅紧急级别)
if ($level === 'EMERGENCY') {
// 发送短信
}
});
$alertManager->sendAlert('CRITICAL', '内存使用超标', [
'memory' => '300MB',
'threshold' => '256MB',
'pid' => 12345,
'script' => '/path/to/script.php'
]);
3 告警抑制机制
避免重复告警骚扰:
<?php
class AlertSuppressor {
private $redis;
private $cooldown = 300; // 5分钟冷却时间
public function shouldSend($alertKey) {
$key = "alert_suppress:{$alertKey}";
if ($this->redis->exists($key)) {
return false; // 冷却期内不发送
}
// 设置冷却期
$this->redis->setex($key, $this->cooldown, 1);
return true;
}
}
最佳实践建议
-
选择适合的监控粒度:
- 线上环境:每分钟检查一次
- 重要业务接口:每次请求都检查
- 批量处理脚本:每处理N条数据检查一次
-
告警分级:
- P0级别:内存使用>90%阈值,立即电话通知
- P1级别:>80%阈值,发送即时消息
- P2级别:>70%阈值,记录日志
-
结合性能分析:
- 内存超标时自动生成内存快照(memory_get_usage配合debug_backtrace)
- 使用Xdebug profiling分析内存泄漏
-
自动化处理:
- 自动重启高内存进程
- 自动扩展资源(如增加FPM进程数)
通过以上方案组合,可以实现对PHP项目内存使用的全方位监控预警,确保问题能够及时发现和处理。
版权声明: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直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播