Windows XAMPP PHP8多进程场景子进程终止后Ajax响应滞后问题咨询
问题根因
- 首先是Session阻塞:默认PHP开启session后,同客户端的并发请求会被session独占锁阻塞,所有请求排队等待前一个请求释放session资源,导致单个请求结束后无法立即返回。
- 其次是管道阻塞问题:现有代码中
fgets读取管道是默认阻塞模式,当ffmpeg子进程被强制终止时,管道的EOF标记不会被即时触发,feof()判断长期不返回true,导致while循环卡死。 - 最后是Apache并发配置不足:Windows版XAMPP默认的Apache MPM配置线程数极低,并发请求占满worker线程后,后续请求的处理会被排队,哪怕对应子进程结束也无法立刻调度返回。
解决方案
1. 释放Session锁
如果你的process.php中调用了session_start(),在完成session相关读写操作后立刻执行session_write_close(),提前释放session锁,避免同客户端请求排队。
2. 改造子进程监听逻辑,使用非阻塞管道+进程状态检查
修改ff_Execute函数逻辑,将管道设为非阻塞模式,每次循环同时检查子进程运行状态,子进程终止后立刻跳出循环返回结果,无需等待管道EOF:
function ff_Execute(){ $descriptorspec = array( 1 => array("pipe", "w"), 2 => array("pipe", "w") // 新增stderr监听,避免错误输出阻塞进程 ); // 用到session则打开下面注释提前释放锁 // session_write_close(); while (@ob_end_flush()); @ob_implicit_flush(true); $process = proc_open("ffmpeg.exe -i *******", $descriptorspec, $pipes); if (!is_resource($process)) { return ['status' => false, 'msg' => '进程启动失败']; } // 将管道设为非阻塞模式 stream_set_blocking($pipes[1], 0); stream_set_blocking($pipes[2], 0); $runStatus = true; while (true) { // 先检查子进程是否还在运行 $pstats = proc_get_status($process); if (!$pstats['running']) { $runStatus = $pstats['exitcode'] === 0; break; } // 非阻塞读取输出 $hb_output = fgets($pipes[1], 90); if ($hb_output !== false) { // 有输出处理需求可在此处添加逻辑 @flush(); @ob_flush(); } // 避免空循环占用过高CPU,加100ms延时 usleep(100000); } fclose($pipes[1]); fclose($pipes[2]); proc_close($process); return ['status' => $runStatus]; }
调用完函数后直接输出JSON并终止脚本,避免后续多余逻辑阻塞返回:
$result = ff_Execute(); echo json_encode($result); exit;
3. 调整Apache并发配置
打开XAMPP安装目录下的apache/conf/extra/httpd-mpm.conf,找到mpm_winnt_module配置段,修改为:
<IfModule mpm_winnt_module> ThreadsPerChild 20 MaxConnectionsPerChild 0 </IfModule>
修改后重启Apache,提升并发处理能力,避免请求排队。
内容的提问来源于stack exchange,提问作者SweetNGX
相关产品推荐
相关产品推荐

