Перейти к содержимому

Устранение неполадок Artisan

Каждый сбой моста проявляется типизированным исключением. Сопоставьте исключение и сообщение с таблицей ниже. Каждая строка указывает на проверку в исходном коде, которая его вызвала, поэтому вы можете устранить причину, а не симптом.

chrome-php/chrome is not installed. Install it via: composer require chrome-php/chrome:^1.15

Клиентской библиотеки Chrome DevTools Protocol (CDP) нет в автозагрузчике. BrowserPool::getBrowser() проверяет её до запуска Chrome. Выполните команду установки. Это не то же самое, что отсутствие исполняемого файла: библиотека и исполняемый файл проверяются на разных этапах.

Chrome renderer failed: <cause>

Chrome не запустился, превысил тайм-аут или аварийно завершился. Предыдущее исключение содержит исходную причину. Проверьте типичные причины:

  • Исполняемый файл не найден / не является исполняемым. Проверьте его командой chromium --headless --dump-dom about:blank. Укажите в chrome_binary абсолютный путь.
  • Песочница не может инициализироваться (контейнеры). В причине упоминается песочница или пространство имён. По возможности используйте контейнер с поддержкой песочницы или установите no_sandbox: true после прочтения /integrations/artisan/security-and-operations/.
  • Тайм-аут. Тяжёлый документ превысил render_timeout. Увеличьте тайм-аут для этой нагрузки или уменьшите документ. В пользовательском пути оцените компромисс с риском отказа в обслуживании.
  • Отсутствуют разделяемые библиотеки. Chrome завершается немедленно. Установите набор зависимостей Chrome для вашего дистрибутива.

Chrome printToPDF returned empty data

Chrome запустился, но printToPDF вернул ноль байт. Обычная причина — входные данные не создают видимого блока: например, тело документа пустое, содержимое имеет значение display:none или Chrome аварийно завершается во время печати. Убедитесь, что входные данные на языке гипертекстовой разметки (HTML) отрисовываются как видимый блок. Проверьте нагрузку на память хоста.

RuntimeException — входные данные отклонены до запуска Chrome

Заголовок раздела «RuntimeException — входные данные отклонены до запуска Chrome»
Сообщение содержитПричинаРешение
exceeds maximum allowed sizeHTML превышает maxHtmlSizeУменьшите входные данные или увеличьте max_html_size (расширяет поверхность для исчерпания ресурсов)
oversized base64 data URIВстроенный data-URI (унифицированный идентификатор ресурса) в формате base64 ≥ 13 МБУменьшите встроенный ресурс; используйте ссылку на изображение меньшего размера
forbidden meta refresh redirect<meta http-equiv="refresh"> присутствуетУдалите этот тег; это вектор навигации для подделки запросов на стороне сервера (SSRF), и он всегда отклоняется

Эти ошибки выдаёт ChromeSecurityPolicy::validate() до обращения к Chrome, поэтому их быстро и недорого покрывать тестами.

Page <n> has no content stream

Chrome создал файл в формате PDF (переносимый формат документов), из которого парсер не смог извлечь страницу. Это случается редко и обычно указывает на некорректный вывод Chrome или на версию Chrome с неожиданной структурой. Зафиксируйте версию Chrome и входные данные. Убедитесь, что исполняемый файл — поддерживаемая сборка Chrome/Chromium.

Это не ошибка. Мост блокирует загрузку каждого подресурса с помощью политики безопасности контента (CSP) default-src 'none' и блокировки CDP setBlockedURLs('*'). Удалённые <img>, таблицы стилей, шрифты, скрипты и iframe не загружаются. Встраивайте ресурсы как URI data:, а каскадные таблицы стилей (CSS) — прямо в документ через defaultCss или <style>. См. сетевую модель на странице /integrations/artisan/security-and-operations/.

Документ перешёл на вторую страницу Chrome, а мост импортировал только страницу 0. Либо буфер автоподгонки был слишком мал для необычно сильного переформатирования, либо явно заданная высота была слишком маленькой. Задайте явную высоту по размеру содержимого или удалите её, чтобы использовать автоподгонку с защитным буфером. См. обработку высоты на странице /integrations/artisan/production-usage/.

Всплеск задержки примерно каждые 100 отрисовок

Заголовок раздела «Всплеск задержки примерно каждые 100 отрисовок»

Это ожидаемое поведение. BrowserPool перезапускает Chrome каждые 100 отрисовок, чтобы ограничить потребление памяти. Строка журнала уровня notice фиксирует перезапуск и количество отрисовок. Учитывайте это как известную периодическую издержку в целевых показателях уровня обслуживания (SLO), а не как инцидент. Если перезапуски происходят чаще, чем раз в 100 отрисовок, документы тяжелее ожидаемого.

Память растёт при длительной пакетной обработке

Заголовок раздела «Память растёт при длительной пакетной обработке»

BrowserPool ограничивает рост памяти за счёт перезапуска каждые 100 отрисовок, но очень долго работающий обработчик всё равно может накапливать память. Вызывайте close() между крупными пакетами, чтобы заранее перезапустить Chrome, и запускайте обработчик с ограничением памяти хоста.

  1. Воспроизведите проблему на минимальном доверенном фрагменте HTML, чтобы отделить проблемы входных данных от проблем окружения.
  2. Выполните chromium --headless --dump-dom about:blank на хосте от имени пользователя обработчика.
  3. Подключите логгер по стандарту PHP Standards Recommendation 3 (PSR-3) и читайте строки уровня info/notice, включая путь к исполняемому файлу и количество перезапусков.
  4. Убедитесь, что chrome-php/chrome установлен: BrowserPool::getBrowser() не выбросит ChromeNotAvailableException, когда он доступен.
  5. Проверьте предыдущее исключение этого исключения, чтобы найти первопричину со стороны Chrome.
  • Установка Artisan: /integrations/artisan/install/
  • Конфигурация Artisan: /integrations/artisan/configuration/
  • Безопасность и эксплуатация: /integrations/artisan/security-and-operations/
  • Настройка отрисовщика Chrome: /integrations/artisan/chrome-renderer-setup/
  • Эксплуатация в продакшене: /integrations/artisan/production-usage/