You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PHP长时脚本触发后不阻塞请求的多环境异常排查

PHP长时脚本后台运行跨环境问题排查

问题背景

编写了一段PHP长时脚本,期望触发后不阻塞后续请求,脚本代码如下:

// filename = htdocs/api/generateFiles.php

ob_end_clean();
header("Connection: close\r\n");
header("Content-Encoding: none\r\n");
ignore_user_abort(true); // optional
set_time_limit(1*3600); // 1 hora max
ob_start();

$filepath = DOL_DOCUMENT_ROOT . '/exports/export-' . date('Ymd-his');
if (!file_exists($filepath)) {
    mkdir($filepath, 0777, true);
}

$sql = "INSERT INTO export_process(folder,fk_user) VALUES ('" . $filepath . "', {$user->id});";
$resSql = $db->query($sql);
if (!$resSql) {
    http_response_code(500); // Internal Server Error
    echo json_encode(['error' => $db->lasterror()]);
    $size = ob_get_length();
    header("Content-Length: $size");
    ob_end_flush();     // Strange behaviour, will not work
    flush();            // Unless both are called !
    ob_end_clean();
    exit();
}

echo json_encode(['success' => true]);
$size = ob_get_length();
header("Content-Length: $size");
ob_end_flush();     // Strange behaviour, will not work
flush();            // Unless both are called !
ob_end_clean();


session_write_close();
// Here goes the long running export function
// Every completed step updates the inserted export_process to increase the completion percentage

三个运行环境表现差异:

  • 本地环境(Windows 11 + XAMPP):AJAX调用后可立即浏览网站,脚本后台运行正常;
  • 测试环境(QNAP NAS Linux):AJAX调用后加载动画持续到脚本结束才显示结果,手动关闭标签页后新标签页仍需等待脚本结束;
  • 生产环境(QNAP NAS Linux):AJAX调用后页面立即刷新,但脚本中途终止(日志显示50步仅执行到第33步)。

已做配置:ignore_user_abort(true)、output_buffering = 4096、session_write_close(),测试与生产环境配置、.htaccess完全一致,但问题仍存在。

可能的排查方向

1. Web服务器层面的输出缓冲/压缩

  • 检查QNAP上Apache是否开启了mod_deflate或mod_gzip,服务器端的强制压缩会忽略脚本中Content-Encoding: none的设置,导致输出无法及时flush到客户端。可以在脚本开头添加apache_setenv('no-gzip', 1);,或者在该脚本所在目录的.htaccess中加入SetEnv no-gzip 1禁用压缩。
  • Apache自身的BufferSize或OutputBufferSize配置可能覆盖PHP的输出缓冲设置,导致输出无法立即发送。可以修改Apache的站点配置,针对该脚本路径关闭输出缓冲。

2. PHP运行模式与进程限制

  • 如果QNAP的PHP采用FastCGI/php-fpm模式运行,检查php-fpm.conf中的request_terminate_timeout参数,生产环境可能设置了较短的超时时间,导致脚本中途被终止,建议将其调整为3600秒以上。同时检查pm.max_requests,避免脚本运行中进程被重启。
  • QNAP NAS系统可能有资源监控机制,当脚本占用CPU/内存过高时会被强制终止,查看系统日志(如/var/log/messages或QTS后台日志)是否有进程被kill的记录。

3. 数据库连接与锁问题

  • 长时脚本中的数据库操作可能持有行锁或表锁,导致后续请求被阻塞。检查export_process表的更新逻辑,确保没有不必要的事务或锁;每完成一步数据库操作后及时commit(若使用事务),避免长时间持有锁。
  • 检查MySQL的wait_timeout参数,如果脚本运行时间超过该值,数据库连接会被断开导致脚本终止。可以在长时脚本中定期执行$db->ping()保持连接,或者调大wait_timeout的值。

4. 文件系统权限与IO瓶颈

  • 生产环境的/exports目录看似设置了0777权限,但QNAP的文件系统可能有ACL权限限制,导致Apache运行用户(如www-data)实际无读写权限,查看系统日志是否有权限错误记录。
  • 生产环境磁盘IO负载过高,导致脚本的文件操作阻塞甚至失败,用iostat命令对比测试与生产环境的磁盘读写性能,排查是否存在IO瓶颈。

5. 网络连接保持设置

  • QNAP的防火墙或网络服务可能开启了连接保持机制,导致服务器不会及时关闭与客户端的连接,进而阻塞后续请求。检查NAS的网络配置,调整连接超时参数。

内容的提问来源于stack exchange,提问作者Daviid

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 07:35:40