在业务系统中,很多核心功能依赖第三方或内部接口提供服务,接口出现异常会直接影响业务正常运行。通过PHP模拟POST请求对接口进行定时监控,配合告警机制,能快速发现接口故障并通知相关人员处理。

一、PHP模拟POST请求的核心实现
PHP模拟POST请求有多种方式,常用的有curl扩展和file_get_contents配合流上下文的方式,其中curl功能更完善,支持设置超时、请求头、代理等参数,更适合监控场景使用。
1.1 使用curl实现POST请求
下面是一个通用的curl模拟POST请求的函数,支持传递请求参数、设置超时时间、自定义请求头:
<?php
/**
* 模拟POST请求函数
* @param string $url 请求地址
* @param array $data 请求参数
* @param array $headers 自定义请求头
* @param int $timeout 超时时间 单位秒
* @return array 包含请求状态、响应内容、耗时等信息
*/
function curlPost($url, $data = [], $headers = [], $timeout = 5) {
$ch = curl_init();
// 设置请求地址
curl_setopt($ch, CURLOPT_URL, $url);
// 设置POST请求
curl_setopt($ch, CURLOPT_POST, true);
// 设置POST参数
if (!empty($data)) {
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
}
// 设置自定义请求头
if (!empty($headers)) {
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
}
// 返回响应结果而不直接输出
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
// 设置超时时间
curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
// 不验证SSL证书 监控场景可关闭提升效率
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
// 记录请求开始时间
$startTime = microtime(true);
$response = curl_exec($ch);
// 记录请求结束时间
$endTime = microtime(true);
// 获取请求错误信息
$error = curl_error($ch);
// 获取HTTP状态码
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
// 关闭curl资源
curl_close($ch);
return [
'http_code' => $httpCode,
'response' => $response,
'error' => $error,
'cost_time' => round(($endTime - $startTime) * 1000, 2) // 耗时 单位毫秒
];
}
?>
1.2 使用file_get_contents实现POST请求(备选方案)
如果服务器没有开启curl扩展,可以使用file_get_contents配合流上下文实现POST请求,不过功能相对有限:
<?php
function filePost($url, $data = [], $timeout = 5) {
$postData = http_build_query($data);
$opts = [
'http' => [
'method' => 'POST',
'header' => "Content-type: application/x-www-form-urlencodedrn" .
"Content-Length: " . strlen($postData) . "rn",
'content' => $postData,
'timeout' => $timeout
]
];
$context = stream_context_create($opts);
$startTime = microtime(true);
$response = file_get_contents($url, false, $context);
$endTime = microtime(true);
// 获取HTTP状态码
$httpCode = 200;
if (isset($http_response_header)) {
foreach ($http_response_header as $header) {
if (preg_match('/HTTP/d.ds+(d+)/', $header, $matches)) {
$httpCode = $matches[1];
break;
}
}
}
return [
'http_code' => $httpCode,
'response' => $response,
'error' => $response === false ? '请求失败' : '',
'cost_time' => round(($endTime - $startTime) * 1000, 2)
];
}
?>
二、接口监控逻辑设计
监控逻辑需要包含接口请求、状态判断、异常记录三个核心环节,我们可以设定监控规则:HTTP状态码不为200、请求耗时超过阈值、响应内容不符合预期都视为接口异常。
2.1 监控规则配置
我们可以先定义监控的配置项,方便后续调整:
<?php
// 监控配置
$monitorConfig = [
// 要监控的接口列表
'interfaces' => [
[
'name' => '用户登录接口',
'url' => 'http://192.168.0.1/api/login',
'method' => 'POST',
'data' => ['username' => 'test', 'password' => 'test123'],
'headers' => ['Content-Type: application/json'],
'timeout' => 3, // 超时时间3秒
'max_cost_time' => 1000, // 最大允许耗时1000毫秒
'expect_response' => 'success' // 响应内容包含该字符串视为正常
],
[
'name' => '订单查询接口',
'url' => 'http://127.0.0.1/api/order_query',
'method' => 'POST',
'data' => ['order_id' => '10001'],
'timeout' => 5,
'max_cost_time' => 2000,
'expect_response' => 'order_info'
]
],
// 告警阈值 连续失败多少次触发告警
'alarm_threshold' => 2,
// 告警通知接收人
'alarm_receivers' => ['admin@ipipp.com']
];
?>
2.2 监控执行逻辑
下面的代码会遍历所有配置的接口,执行请求并判断状态,记录异常信息:
<?php
// 存储接口状态 用于判断是否达到告警阈值
$interfaceStatus = [];
// 存储异常信息
$errorLogs = [];
foreach ($monitorConfig['interfaces'] as $interface) {
$url = $interface['url'];
$data = $interface['data'];
$headers = $interface['headers'] ?? [];
$timeout = $interface['timeout'] ?? 5;
// 执行POST请求
$result = curlPost($url, $data, $headers, $timeout);
$isError = false;
$errorMsg = '';
// 判断HTTP状态码
if ($result['http_code'] != 200) {
$isError = true;
$errorMsg .= "HTTP状态码异常:{$result['http_code']};";
}
// 判断请求错误
if (!empty($result['error'])) {
$isError = true;
$errorMsg .= "请求错误:{$result['error']};";
}
// 判断耗时
if ($result['cost_time'] > $interface['max_cost_time']) {
$isError = true;
$errorMsg .= "请求耗时过长:{$result['cost_time']}毫秒;";
}
// 判断响应内容
if (!empty($interface['expect_response']) && strpos($result['response'], $interface['expect_response']) === false) {
$isError = true;
$errorMsg .= "响应内容不符合预期;";
}
// 记录接口状态
$interfaceKey = $interface['name'];
if (!isset($interfaceStatus[$interfaceKey])) {
$interfaceStatus[$interfaceKey] = 0;
}
if ($isError) {
$interfaceStatus[$interfaceKey]++;
$errorLogs[] = [
'time' => date('Y-m-d H:i:s'),
'interface' => $interface['name'],
'msg' => $errorMsg,
'request_info' => [
'url' => $url,
'cost_time' => $result['cost_time'],
'http_code' => $result['http_code']
]
];
} else {
// 正常则重置计数
$interfaceStatus[$interfaceKey] = 0;
}
}
?>
三、告警通知实现
当接口连续异常次数达到阈值时,需要触发告警通知,常用的通知方式有邮件、企业微信、钉钉等,这里以邮件告警为例,PHP可以通过mail函数或者PHPMailer扩展发送邮件。
3.1 邮件告警函数实现
下面是使用mail函数发送告警邮件的示例,如果使用PHPMailer可以替换对应逻辑:
<?php
/**
* 发送告警邮件
* @param string $subject 邮件主题
* @param string $body 邮件内容
* @param array $receivers 收件人列表
* @return bool 是否发送成功
*/
function sendAlarmEmail($subject, $body, $receivers) {
$to = implode(',', $receivers);
$headers = "From: monitor@ipipp.comrn";
$headers .= "Content-type: text/html; charset=utf-8rn";
return mail($to, $subject, $body, $headers);
}
?>
3.2 触发告警逻辑
遍历接口状态,达到阈值则发送告警:
<?php
// 遍历接口状态 触发告警
foreach ($interfaceStatus as $interfaceName => $errorCount) {
if ($errorCount >= $monitorConfig['alarm_threshold']) {
// 拼接告警内容
$alarmSubject = "【接口告警】{$interfaceName}连续异常{$errorCount}次";
$alarmBody = "<h3>接口告警通知</h3>";
$alarmBody .= "<p>告警时间:" . date('Y-m-d H:i:s') . "</p>";
$alarmBody .= "<p>接口名称:{$interfaceName}</p>";
$alarmBody .= "<p>连续异常次数:{$errorCount}</p>";
$alarmBody .= "<p>异常详情:</p>";
$alarmBody .= "<ul>";
foreach ($errorLogs as $log) {
if ($log['interface'] == $interfaceName) {
$alarmBody .= "<li>{$log['time']}:{$log['msg']}</li>";
}
}
$alarmBody .= "</ul>";
// 发送告警
$sendResult = sendAlarmEmail($alarmSubject, $alarmBody, $monitorConfig['alarm_receivers']);
if ($sendResult) {
echo "告警邮件发送成功:{$interfaceName}n";
} else {
echo "告警邮件发送失败:{$interfaceName}n";
}
}
}
?>
四、定时执行监控任务
监控需要定时执行,在Linux系统中可以通过crontab配置定时任务,比如每分钟执行一次监控脚本:
# 编辑crontab任务 crontab -e # 添加如下内容 每分钟执行一次监控脚本 * * * * * /usr/bin/php /path/to/monitor_script.php >> /tmp/monitor.log 2>&1
如果是Windows系统,可以使用任务计划程序配置定时执行PHP脚本。
五、注意事项
- 监控脚本的执行用户需要有访问网络和发送邮件的权限,避免权限不足导致监控失效。
- 超时时间需要根据接口的实际响应情况设置,不要设置过短导致误判,也不要设置过长影响监控及时性。
- 告警阈值建议设置为2-3次,避免网络波动导致的偶发异常触发误告警。
- 可以定期清理监控日志,避免日志文件过大占用磁盘空间。
- 如果监控的是HTTPS接口,建议开启SSL证书验证,保证请求的安全性。