本文目录导读:

- 使用循环与异常捕获(基础保活)
- 使用信号处理(优雅退出)
- 使用 Supervisor(推荐方式)
- 使用 systemd(Linux 系统推荐)
- 自愈型守护进程(PHP 内置 fallback)
- 进阶技巧:内存监控与重启
- 防止内存泄漏
- 完整的保活方案示例
在 PHP 中实现守护进程的“保活”(即防止进程意外退出或崩溃后无法恢复)有多种策略,以下是几种常用的方法和最佳实践:
使用循环与异常捕获(基础保活)
这是最直接的方式,通过无限循环让进程持续运行,并处理可能出现的异常。
<?php
declare(ticks=1);
// 设置为守护进程(脱离终端)
function daemonize() {
$pid = pcntl_fork();
if ($pid == -1) {
die('fork failed');
} elseif ($pid > 0) {
exit(0); // 父进程退出
}
// 子进程成为会话领导者
if (posix_setsid() == -1) {
die('setsid failed');
}
// 二次 fork 防止重新获取控制终端
$pid = pcntl_fork();
if ($pid == -1) {
die('fork failed');
} elseif ($pid > 0) {
exit(0);
}
// 切换工作目录
chdir('/');
// 关闭标准输入输出
fclose(STDIN);
fclose(STDOUT);
fclose(STDERR);
}
在循环中捕获异常,避免进程崩溃:
while (true) {
try {
// 你的业务逻辑
processTask();
} catch (Throwable $e) {
// 记录错误日志
logError($e->getMessage());
// 稍作延迟,避免死循环导致 CPU 100%
sleep(1);
}
// 防止内存溢出,定期清理
gc_collect_cycles();
}
使用信号处理(优雅退出)
通过捕获信号(如 SIGTERM、SIGINT)来实现优雅关闭,而不是直接杀死进程。
<?php
// 声明信号处理器
pcntl_async_signals(true);
$running = true;
function shutdown() {
global $running;
$running = false;
}
pcntl_signal(SIGTERM, 'shutdown');
pcntl_signal(SIGINT, 'shutdown');
while ($running) {
// 业务逻辑
processTask();
sleep(1);
}
// 清理资源
cleanup();
使用 Supervisor(推荐方式)
这是目前最主流、最可靠的方式。Supervisor 是一个进程管理工具,专门用来监控和管理进程。
配置示例 (/etc/supervisor/conf.d/my-worker.conf):
[program:my-worker] command=php /path/to/worker.php directory=/path/to/project autostart=true autorestart=true startretries=10 startsecs=3 redirect_stderr=true stdout_logfile=/var/log/worker.out.log stderr_logfile=/var/log/worker.err.log stopwaitsecs=5
优势:
- 崩溃后自动重启
- 可以配置重启策略(如重启尝试次数)
- 日志管理完善
- 支持在服务器启动时自动加载
使用 systemd(Linux 系统推荐)
将 PHP 守护进程注册为 systemd 服务,利用 systemd 的进程管理能力。
创建 /etc/systemd/system/my-worker.service:
[Unit] Description=PHP Worker Daemon After=network.target [Service] Type=simple User=www-data Group=www-data ExecStart=/usr/bin/php /path/to/worker.php Restart=always RestartSec=10 KillSignal=SIGQUIT TimeoutStopSec=10 [Install] WantedBy=multi-user.target
启用并启动服务:
systemctl daemon-reload systemctl enable my-worker systemctl start my-worker
自愈型守护进程(PHP 内置 fallback)
如果环境不允许安装 Supervisor 或 systemd,可以通过一个“监视进程”来实现自我修复。
<?php
// auto_restart.php
while (true) {
$command = "php /path/to/worker.php";
$output = [];
$return_var = 0;
echo "Starting worker...\n";
exec($command, $output, $return_var);
echo "Worker exited with code: $return_var\n";
// 如果是正常退出(例如收到停止信号),则退出监视器
if ($return_var === 0) {
break;
}
// 等待后重新启动
sleep(2);
}
进阶技巧:内存监控与重启
在守护进程内部监控内存使用情况,当内存占用超过阈值时,优雅退出,让外层监控工具(如 Supervisor)重启。
while (true) {
$memory_usage = memory_get_usage(true);
if ($memory_usage > 500 * 1024 * 1024) { // 500MB 阈值
logError("Memory limit reached: {$memory_usage}");
exit(0); // 正常退出,由 Supervisor 自动重启
}
processTask();
// 定期释放临时资源
unset($tempData);
gc_collect_cycles();
usleep(100000); // 100ms 休眠
}
防止内存泄漏
长期运行的 PHP 进程最需要注意的是内存泄漏问题:
- 使用
unset()释放大型对象和数组 - 使用
gc_collect_cycles()强制垃圾回收 - 避免闭包持有上下文引用
- 定期重新初始化实例
while (true) {
// 每次循环创建新的资源,而不是复用一个长期实例
$db = getDatabaseConnection();
processTask($db);
$db = null; // 释放连接
// 清理输出缓冲
if (ob_get_level() > 0) {
ob_end_clean();
}
sleep(1);
}
完整的保活方案示例
结合以上所有技巧的守护进程模板:
<?php
declare(ticks=1);
// 1. 守护化
daemonize();
// 2. 设置信号处理器
pcntl_async_signals(true);
$running = true;
pcntl_signal(SIGTERM, function() use (&$running) {
$running = false;
});
// 3. 主循环
while ($running) {
try {
$memory = memory_get_usage(true);
if ($memory > 500 * 1024 * 1024) {
throw new RuntimeException("Memory limit exceeded");
}
processTask();
} catch (Throwable $e) {
file_put_contents('/var/log/worker_errors.log',
date('Y-m-d H:i:s') . " - " . $e->getMessage() . PHP_EOL,
FILE_APPEND);
if ($e->getMessage() === "Memory limit exceeded") {
exit(0); // 让 Supervisor 重启
}
sleep(1);
}
gc_collect_cycles();
usleep(100000);
}
function processTask() {
// 实际业务逻辑
// ...
}
| 策略 | 适用场景 | 可靠性 |
|---|---|---|
| Supervisor | 生产环境 | |
| systemd | Linux 系统服务 | |
| 循环+异常捕获 | 简单应用 | |
| 信号处理+循环 | 需要优雅关闭 | |
| 自愈监控进程 | 无外部依赖 |
推荐使用 Supervisor 或 systemd,它们提供最稳定、最完善的进程生命周期管理,而且不需要修改你的 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直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播