Browse Source

优化合并 pdf 功能

yemeishu 12 giờ trước cách đây
mục cha
commit
25be3606f3
1 tập tin đã thay đổi với 44 bổ sung21 xóa
  1. 44 21
      app/Services/ExamPdfExportService.php

+ 44 - 21
app/Services/ExamPdfExportService.php

@@ -1270,13 +1270,11 @@ class ExamPdfExportService
 
         $process = new Process([
             $chromeBinary,
-            '--headless',
+            '--headless=new',
             '--disable-gpu',
             '--no-sandbox',
             '--disable-setuid-sandbox',
             '--disable-dev-shm-usage',
-            '--no-zygote',
-            '--disable-features=VizDisplayCompositor',
             '--disable-software-rasterizer',
             '--disable-extensions',
             '--disable-background-networking',
@@ -1299,44 +1297,66 @@ class ExamPdfExportService
             '--disable-backgrounding-occluded-windows',
             '--disable-renderer-backgrounding',
             '--disable-features=AudioServiceOutOfProcess',
+            '--disable-gpu-rasterization',
+            '--disable-web-security',
+            '--disable-features=VizDisplayCompositor',
+            '--font-render-hinting=none',
             '--user-data-dir=' . $userDataDir,
             '--print-to-pdf=' . $tmpPdf,
             '--print-to-pdf-no-header',
             '--allow-file-access-from-files',
+            '--virtual-time-budget=10000',
+            '--run-all-compositor-stages-before-draw',
             'file://' . $htmlPath,
         ], null, [
             'HOME' => $runtimeHome,
             'XDG_RUNTIME_DIR' => $runtimeXdg,
         ]);
 
-        // 【修复】减少超时时间,避免队列任务整体超时
-        // 队列任务默认60秒超时,给Chrome进程设置45秒超时
-        $process->setTimeout(45);
+        // 【修复】进一步缩短超时时间,提高响应速度
+        // 设置30秒超时,快速失败避免长时间等待
+        $process->setTimeout(30);
         $killSignal = \defined('SIGKILL') ? \SIGKILL : 9;
 
         try {
             $startedAt = microtime(true);
             Log::info('ExamPdfExportService: Chrome进程启动', [
                 'start_time' => date('Y-m-d H:i:s', (int)$startedAt),
-                'timeout' => 45
+                'timeout' => 30,
+                'html_size' => file_exists($htmlPath) ? filesize($htmlPath) : 0
             ]);
 
             $process->start();
             $pdfGenerated = false;
 
-            // 【修复】缩短轮询时间,提高响应速度
+            // 【修复】进一步缩短轮询时间,提高响应速度
             $pollStart = microtime(true);
-            $maxPollSeconds = 40; // 缩短到40秒(小于Chrome超时45秒)
-            $checkInterval = 100_000; // 100ms检查一次
+            $maxPollSeconds = 28; // 缩短到28秒(小于Chrome超时30秒)
+            $checkInterval = 50_000; // 50ms检查一次(更频繁)
+
+            // 初始等待1秒让Chrome启动
+            usleep(1_000_000);
 
             while ($process->isRunning() && (microtime(true) - $pollStart) < $maxPollSeconds) {
+                // 每2秒输出一次进度
+                $currentElapsed = microtime(true) - $pollStart;
+                if (fmod($currentElapsed, 2) < 0.1 || $currentElapsed < 0.2) {
+                    Log::debug('ExamPdfExportService: Chrome渲染中', [
+                        'elapsed' => round($currentElapsed, 2) . 's',
+                        'pdf_exists' => file_exists($tmpPdf),
+                        'pdf_size' => file_exists($tmpPdf) ? filesize($tmpPdf) : 0
+                    ]);
+                }
+
                 if (file_exists($tmpPdf) && filesize($tmpPdf) > 0) {
                     $pdfGenerated = true;
+                    $elapsed = microtime(true) - $startedAt;
                     Log::info('ExamPdfExportService: PDF文件已生成,提前终止Chrome', [
-                        'elapsed' => round(microtime(true) - $startedAt, 2) . 's',
-                        'pdf_size' => filesize($tmpPdf)
+                        'elapsed' => round($elapsed, 2) . 's',
+                        'pdf_size' => filesize($tmpPdf),
+                        'poll_elapsed' => round($currentElapsed, 2) . 's'
                     ]);
-                    $process->stop(2, $killSignal);
+                    $process->stop(1, $killSignal);
                     break;
                 }
                 usleep($checkInterval);
@@ -1347,15 +1367,17 @@ class ExamPdfExportService
                 'elapsed' => round($elapsed, 2) . 's',
                 'is_running' => $process->isRunning(),
                 'pdf_exists' => file_exists($tmpPdf),
-                'pdf_size' => file_exists($tmpPdf) ? filesize($tmpPdf) : 0
+                'pdf_size' => file_exists($tmpPdf) ? filesize($tmpPdf) : 0,
+                'timeout' => $maxPollSeconds
             ]);
 
-            // 【优化】强制停止Chrome进程
+            // 【优化】强制快速停止Chrome进程
             if ($process->isRunning()) {
                 Log::warning('ExamPdfExportService: Chrome进程仍在运行,强制停止', [
-                    'elapsed' => round($elapsed, 2) . 's'
+                    'elapsed' => round($elapsed, 2) . 's',
+                    'reason' => 'timeout'
                 ]);
-                $process->stop(2, $killSignal);
+                $process->stop(1, $killSignal);
             }
 
             $process->wait();
@@ -1364,10 +1386,11 @@ class ExamPdfExportService
             Log::error('ExamPdfExportService: Chrome进程超时', [
                 'timeout' => $e->getExceededTimeout(),
                 'elapsed' => round(microtime(true) - $startedAt, 2) . 's',
-                'html_size' => file_exists($htmlPath) ? filesize($htmlPath) : 0
+                'html_size' => file_exists($htmlPath) ? filesize($htmlPath) : 0,
+                'message' => 'Chrome渲染超时,已自动终止'
             ]);
             if ($process->isRunning()) {
-                $process->stop(2, $killSignal);
+                $process->stop(1, $killSignal);
             }
             return $this->handleChromeProcessResult($tmpPdf, $userDataDir, $process, $startedAt);
         } catch (ProcessSignaledException $e) {
@@ -1376,7 +1399,7 @@ class ExamPdfExportService
                 'elapsed' => round(microtime(true) - $startedAt, 2) . 's'
             ]);
             if ($process->isRunning()) {
-                $process->stop(2, $killSignal);
+                $process->stop(1, $killSignal);
             }
             return $this->handleChromeProcessResult($tmpPdf, $userDataDir, $process, $startedAt);
         } catch (\Throwable $e) {
@@ -1386,7 +1409,7 @@ class ExamPdfExportService
                 'trace' => $e->getTraceAsString()
             ]);
             if ($process->isRunning()) {
-                $process->stop(2, $killSignal);
+                $process->stop(1, $killSignal);
             }
             return $this->handleChromeProcessResult($tmpPdf, $userDataDir, $process, null);
         }