本文目录导读:

在PHP项目中实现探针接口(通常用于健康检查、性能监控或环境诊断),主要有以下几种常用方法和最佳实践。
基础健康检查探针
最简单的探针,用于检测服务是否存活。
// health.php
<?php
header('Content-Type: application/json');
$status = [
'status' => 'ok',
'timestamp' => time(),
'service' => 'my-php-app'
];
echo json_encode($status);
完整的环境诊断探针
包含系统信息、PHP配置、数据库连接等详细检测。
// probe.php
<?php
class Probe {
private $checks = [];
private $status = 'ok';
public function run() {
$this->checkPHPVersion();
$this->checkExtensions();
$this->checkDatabase();
$this->checkDiskSpace();
$this->checkMemory();
$this->checkUptime();
return $this->generateResponse();
}
private function checkPHPVersion() {
$this->checks['php_version'] = [
'value' => PHP_VERSION,
'status' => version_compare(PHP_VERSION, '7.4', '>=') ? 'ok' : 'warning'
];
}
private function checkExtensions() {
$required = ['pdo', 'pdo_mysql', 'json', 'mbstring', 'openssl'];
$missing = [];
foreach ($required as $ext) {
if (!extension_loaded($ext)) {
$missing[] = $ext;
}
}
$this->checks['extensions'] = [
'required' => $required,
'missing' => $missing,
'status' => empty($missing) ? 'ok' : 'error'
];
}
private function checkDatabase() {
try {
$db = new PDO(
'mysql:host=localhost;dbname=test;charset=utf8mb4',
'username',
'password',
[PDO::ATTR_TIMEOUT => 3]
);
$this->checks['database'] = [
'status' => 'ok',
'message' => '数据库连接正常'
];
} catch (PDOException $e) {
$this->checks['database'] = [
'status' => 'error',
'message' => '数据库连接失败: ' . $e->getMessage()
];
$this->status = 'error';
}
}
private function checkDiskSpace() {
$diskFree = disk_free_space('/');
$diskTotal = disk_total_space('/');
$usagePercent = round((1 - $diskFree / $diskTotal) * 100, 2);
$this->checks['disk_space'] = [
'free' => $this->formatBytes($diskFree),
'total' => $this->formatBytes($diskTotal),
'usage_percent' => $usagePercent . '%',
'status' => $usagePercent < 90 ? 'ok' : 'warning'
];
}
private function checkMemory() {
$this->checks['memory'] = [
'memory_limit' => ini_get('memory_limit'),
'memory_usage' => $this->formatBytes(memory_get_usage()),
'peak_memory' => $this->formatBytes(memory_get_peak_usage()),
'status' => 'ok'
];
}
private function checkUptime() {
if (PHP_OS_FAMILY === 'Linux') {
$uptime = file_get_contents('/proc/uptime');
$seconds = floatval(explode(' ', $uptime)[0]);
$this->checks['uptime'] = [
'value' => $this->formatTime($seconds),
'status' => 'ok'
];
}
}
private function formatBytes($bytes) {
$units = ['B', 'KB', 'MB', 'GB', 'TB'];
$i = 0;
while ($bytes >= 1024 && $i < count($units) - 1) {
$bytes /= 1024;
$i++;
}
return round($bytes, 2) . ' ' . $units[$i];
}
private function formatTime($seconds) {
$days = floor($seconds / 86400);
$hours = floor(($seconds % 86400) / 3600);
$minutes = floor(($seconds % 3600) / 60);
return "{$days}天 {$hours}小时 {$minutes}分钟";
}
private function generateResponse() {
header('Content-Type: application/json');
return json_encode([
'status' => $this->status,
'timestamp' => time(),
'hostname' => gethostname(),
'server_ip' => $_SERVER['SERVER_ADDR'] ?? 'unknown',
'checks' => $this->checks
], JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
}
}
$probe = new Probe();
echo $probe->run();
安全增强的探针
防止未授权访问。
// secure_probe.php
<?php
class SecureProbe {
private $apiKey;
private $allowedIps = [];
private $rateLimit = [];
public function __construct() {
// 从环境变量获取API密钥
$this->apiKey = $_ENV['PROBE_API_KEY'] ?? getenv('PROBE_API_KEY');
// 允许的IP白名单
$this->allowedIps = [
'127.0.0.1',
'::1',
'192.168.1.0/24'
];
}
public function authenticate() {
$clientIp = $_SERVER['REMOTE_ADDR'];
// IP白名单检查
if (!$this->checkIpWhitelist($clientIp)) {
$this->denyAccess('IP not allowed');
}
// API密钥验证
$requestKey = $_GET['key'] ?? $_SERVER['HTTP_X_PROBE_KEY'] ?? '';
if ($this->apiKey && $requestKey !== $this->apiKey) {
$this->denyAccess('Invalid API key');
}
// 速率限制
if (!$this->checkRateLimit($clientIp)) {
$this->denyAccess('Rate limit exceeded');
}
return true;
}
private function checkIpWhitelist($ip) {
foreach ($this->allowedIps as $allowed) {
if (strpos($allowed, '/') !== false) {
// CIDR检查
if ($this->cidrMatch($ip, $allowed)) {
return true;
}
} else {
if ($ip === $allowed) {
return true;
}
}
}
return false;
}
private function cidrMatch($ip, $cidr) {
list($subnet, $mask) = explode('/', $cidr);
$ipLong = ip2long($ip);
$subnetLong = ip2long($subnet);
$maskLong = -1 << (32 - $mask);
return ($ipLong & $maskLong) === ($subnetLong & $maskLong);
}
private function checkRateLimit($ip) {
$window = 60; // 60秒窗口
$limit = 10; // 最多10次请求
$cacheFile = sys_get_temp_dir() . '/probe_rate_' . md5($ip);
if (file_exists($cacheFile)) {
$data = json_decode(file_get_contents($cacheFile), true);
$currentTime = time();
// 清理过期记录
$data = array_filter($data, function($timestamp) use ($currentTime, $window) {
return $timestamp > ($currentTime - $window);
});
if (count($data) >= $limit) {
return false;
}
$data[] = $currentTime;
} else {
$data = [time()];
}
file_put_contents($cacheFile, json_encode($data));
return true;
}
private function denyAccess($reason) {
http_response_code(403);
header('Content-Type: application/json');
echo json_encode([
'status' => 'error',
'message' => 'Access denied: ' . $reason
]);
exit;
}
}
// 使用示例
$secureProbe = new SecureProbe();
$secureProbe->authenticate();
// ... 继续执行探针逻辑
中间件式探针(适用于框架)
以Laravel为例的路由定义:
// routes/api.php
Route::get('/health', function () {
return response()->json([
'status' => 'ok',
'timestamp' => now()->timestamp
]);
});
// 详细探针带认证
Route::middleware(['probe.auth'])->get('/probe', 'ProbeController@index');
对应的中间件:
// app/Http/Middleware/ProbeAuth.php
<?php
namespace App\Http\Middleware;
use Closure;
class ProbeAuth
{
public function handle($request, Closure $next)
{
$apiKey = config('app.probe_api_key');
if ($apiKey && $request->header('X-Probe-Key') !== $apiKey) {
return response()->json(['error' => 'Unauthorized'], 401);
}
return $next($request);
}
}
使用现成的探针库
推荐几个常用的PHP探针库:
Composer包安装
composer require abraham/twitteroauth # 其他用途,仅作示例
常用的专业探针库:
- php-health-check:
composer require php-health-check/health-check - laminas/laminas-diagnostics:
composer require laminas/laminas-diagnostics - enrise/healthcheck:
composer require enrise/healthcheck
使用php-health-check示例
// 使用第三方库实现
require 'vendor/autoload.php';
use Laminas\Diagnostics\Check\PhpVersion;
use Laminas\Diagnostics\Runner\Runner;
$runner = new Runner();
$runner->addCheck(new PhpVersion('7.4'));
$results = $runner->run();
$data = [];
foreach ($results as $checkName => $result) {
$data['checks'][$checkName] = [
'status' => $result->getStatus() ? 'ok' : 'fail',
'message' => $result->getDescription()
];
}
echo json_encode($data);
Nginx配置示例
保护探针接口不被公网直接访问:
# nginx配置
location /probe {
# 仅允许内网访问
allow 127.0.0.1;
allow 192.168.0.0/16;
allow 10.0.0.0/8;
deny all;
# 或者通过密码保护
auth_basic "Probe Access";
auth_basic_user_file /etc/nginx/.htpasswd_probe;
try_files $uri /index.php?$args;
}
最佳实践建议
-
安全性优先
- 使用API密钥验证
- IP白名单限制
- HTTPS传输
- 速率限制
-
不要暴露敏感信息
- 不要显示数据库密码
- 不要显示文件系统路径
- 生产环境限制详情输出
-
监控与告警
- 配置外部监控服务(如Prometheus、New Relic)
- 设置状态码对应(200=正常,503=异常)
- 集成日志记录
-
性能考虑
- 探针请求不应影响正常业务
- 使用缓存减少数据库查询
- 设置超时时间(如3秒)
根据你的项目规模和需求选择合适的方案,对于小型项目,基础的健康检查就足够;对于生产环境,建议使用安全增强的探针并集成监控系统。
版权声明:足球直播
足球直播
足球直播
足球直播
足球直播
中超直播
中超直播
中超直播
中超直播
中超直播
英超直播
英超直播
英超直播
英超直播
英超直播
德甲直播
德甲直播
德甲直播
德甲直播
德甲直播
西甲直播
西甲直播
西甲直播
西甲直播
西甲直播
意甲直播
意甲直播
意甲直播
意甲直播
意甲直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
足球直播
足球直播
足球直播
足球直播
足球直播
中超直播
中超直播
中超直播
中超直播
中超直播
英超直播
英超直播
英超直播
英超直播
英超直播
德甲直播
德甲直播
德甲直播
德甲直播
德甲直播
西甲直播
西甲直播
西甲直播
西甲直播
西甲直播
意甲直播
意甲直播
意甲直播
意甲直播
意甲直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
足球直播
足球直播
足球直播
足球直播
足球直播
中超直播
中超直播
中超直播
中超直播
中超直播
英超直播
英超直播
英超直播
英超直播
英超直播
德甲直播
德甲直播
德甲直播
德甲直播
德甲直播
西甲直播
西甲直播
西甲直播
西甲直播
西甲直播
意甲直播
意甲直播
意甲直播
意甲直播
意甲直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播