Artisan im Produktionsbetrieb
Auf einen Blick
Abschnitt betitelt „Auf einen Blick“Im Produktionsbetrieb injizieren Sie einen konfigurierten Renderer und einen PSR-3-Logger, verwenden den laufenden Chrome-Prozess über mehrere Renderings hinweg wieder, geben für Dokumente mit mehreren Elementen explizite Höhen an und begrenzen den Render-Pfad mit einem vorgelagerten Timeout.
Konzeptioneller Überblick
Abschnitt betitelt „Konzeptioneller Überblick“BrowserPool hält einen Chrome-Prozess am Leben (keepAlive: true) und startet ihn alle 100 Renderings neu, um das Speicherwachstum zu begrenzen — ein bekanntes Akkumulationsmuster bei langlebigen CDP-Clients. Für einen Worker, der viele Dokumente rendert, verwenden Sie einen einzigen langlebigen Renderer statt eines Renderers pro Anfrage, damit die Chrome-Startkosten nur selten anfallen.
Codebeispiel — Produktion
Abschnitt betitelt „Codebeispiel — Produktion“<?php
declare(strict_types=1);
use NextPDF\Artisan\ChromeHtmlRenderer;use NextPDF\Artisan\ChromeRendererConfig;use NextPDF\Artisan\Exception\ChromeNotAvailableException;use NextPDF\Artisan\Exception\ChromeRenderException;use Psr\Log\LoggerInterface;
final class ReportRenderer{ private ChromeHtmlRenderer $renderer;
public function __construct(LoggerInterface $logger) { $config = ChromeRendererConfig::fromArray([ 'chrome_binary' => getenv('CHROME_BINARY') ?: null, 'render_timeout' => 45, 'max_html_size' => 2_000_000, 'no_sandbox' => (bool) getenv('CHROME_NO_SANDBOX'), ]);
$this->renderer = new ChromeHtmlRenderer($config, $logger); }
public function render(string $html, float $widthPt, float $heightPt = 0.0): string { try { return $this->renderer->render($html, $widthPt, $heightPt)->getPdfData(); } catch (ChromeNotAvailableException $e) { // Deployment fault: Chrome runtime missing. Page the on-call owner. throw $e; } catch (ChromeRenderException $e) { // Render-time fault: timeout, crash, empty output. Retryable once. throw $e; } }
public function shutdown(): void { $this->renderer->close(); }}Der Renderer wird einmal erstellt und wiederverwendet. close() wird beim Worker-Shutdown aufgerufen, um den Chrome-Prozess deterministisch freizugeben, statt auf den Destruktor zu warten. Die beiden catch-Zweige trennen einen Deployment-Fehler (fehlende Runtime) von einem Render-Fehler (wiederholbar). Leere catch-Blöcke werden nicht verwendet.
Registrieren Sie ihn als Singleton in einem Container:
$container->singleton(ReportRenderer::class, fn ($c) => new ReportRenderer($c->get(Psr\Log\LoggerInterface::class)));Höhenbehandlung
Abschnitt betitelt „Höhenbehandlung“Wird die Höhe weggelassen, misst die Brücke die Inhaltshöhe in Chrome (max der Scroll- und Offset-Höhen von body/document), wandelt sie in Punkte um und fügt einen Sicherheitspuffer von ~0,2 Zoll (~14,4 pt) hinzu. Der Puffer gleicht den Unterschied zwischen dem Viewport-Layout von Chrome und seinem Print-Layout-Reflow aus. Ohne ihn kann printToPDF auf eine zweite Seite überlaufen, die PageImporter (nur Seite 0) abschneiden würde. Eine minimale Papierhöhe von 0,1 Zoll wird erzwungen. Die Tests ChromeHtmlRendererTest::renderUsesAutoFitHeightByDefault, ::renderAutoFitBufferIsAddedNotSubtracted und ::renderAppliesMinimumHeightOf0Point1InchForTinyExplicitHeight stellen dies sicher.
Für Dokumente mit festem Layout (Rechnungen, Zertifikate) geben Sie eine explizite Höhe in Punkten an. Bei expliziter Höhe wird kein Puffer hinzugefügt; die Ausgabe entspricht exakt der angeforderten Papiergröße (zugesichert durch ::renderHonorsExplicitHeightWithoutAutoBuffer).
Batch-Worker
Abschnitt betitelt „Batch-Worker“- Erstellen Sie einen Renderer pro Worker und verwenden Sie ihn wieder.
BrowserPoolverwendet den laufenden Browser weiter und startet ihn automatisch an der 100-Rendering-Grenze neu. - Rufen Sie
close()beim Worker-Shutdown und zwischen großen Batches auf, wenn Sie vor der 100-Rendering-Grenze einen frischen Chrome-Prozess benötigen. - Der Destruktor ruft
close()auf; ein explizitesclose()ist jedoch deterministisch und in langlaufenden Prozessen vorzuziehen. - Neustart-Hinweise werden auf
notice-Level mit der Render-Anzahl protokolliert — lösen Sie bei einer erhöhten Neustartrate einen Alarm aus, die auf schwerere Dokumente als erwartet hindeutet.
Observability
Abschnitt betitelt „Observability“Injizieren Sie einen PSR-3-Logger. Ausgelöste Events und ihre Level:
| Event | Level | Kontext |
|---|---|---|
| Render-Start | debug | size, width, height |
| Render abgeschlossen | debug | pdfSize, contentHeight |
| Browser-Start | info | binary |
| Browser-Neustart | notice | count |
| Browser-Close | debug | renderCount |
Es werden kein HTML, keine PDF-Bytes und kein extrahierter Text protokolliert, im Einklang mit den Empfehlungen aus NIST SP 800-92, Payloads aus den Betriebsprotokollen herauszuhalten. Bilden Sie Latenz-SLOs aus dem start/complete-Paar und einen Alarm für die Neustartrate aus den notice-Events.
Deployment-Muster
Abschnitt betitelt „Deployment-Muster“- Sidecar-Chrome: Führen Sie Chrome im selben Container wie den PHP-Worker aus; pinnen Sie
chrome_binary. Stellen Sie einen sandbox-fähigen Container bereit — siehe /integrations/artisan/chrome-renderer-setup/. - Containerlos / CLI: Artisan hat keinen DI-Container. Verwenden Sie
EInvoiceServiceFactoryfür Premium-E-Invoice-Verträge in CLI-Runnern; siehe /integrations/artisan/boot-and-discovery/. - Ressourcenbegrenzung: Kombinieren Sie
render_timeoutmit einem vorgelagerten Anfragebudget und einem hostseitigen cgroup/ulimit. Siehe das Bedrohungsmodell unter /integrations/artisan/security-and-operations/.
Edge Cases & Fallstricke
Abschnitt betitelt „Edge Cases & Fallstricke“- Wenn ein Rendering mittendrin abgefangen wird, schließt der Renderer die Chrome-Seite trotzdem (
finally); der Pool bleibt nutzbar. - Die Wiederverwendung eines einzigen Renderers über threads/processes hinweg wird nicht unterstützt; ein Renderer besitzt einen Chrome-Prozess.
- Der Neustart nach 100 Renderings ist fest vorgegeben; dimensionieren Sie Batches entsprechend, damit Latenzspitzen vorhersehbar bleiben.
Performance
Abschnitt betitelt „Performance“Die Kosten im eingeschwungenen Zustand bestehen aus dem Chrome-Layout der Eingabe plus printToPDF, nicht aus dem Overhead der Brücke. Die Startkosten werden durch keepAlive amortisiert. Rechnen Sie bei jedem 100. Rendering mit einer Latenzspitze (Prozessneustart) — bilden Sie sie in den SLOs ab, statt sie als Incident zu behandeln.
Sicherheitshinweise
Abschnitt betitelt „Sicherheitshinweise“Produktionspfade sind die Stellen, an denen nicht vertrauenswürdiges HTML eintrifft. Lesen Sie /integrations/artisan/security-and-operations/. erneut. Die Netzwerkbarrieren greifen unabhängig von der Konfiguration, aber no_sandbox: true entfernt die Chrome-Prozessisolation und erhöht die Vertrauensanforderung an die Eingabe.
Kommerzieller Kontext
Abschnitt betitelt „Kommerzieller Kontext“In containerlosen Workern gibt EInvoiceServiceFactory null zurück, wenn Premium nicht installiert ist, sodass der Open-Source-Render-Pfad unverändert läuft; installieren Sie Pro/Enterprise, um E-Invoice-Einbettung und -Validierung auf dem gerenderten Dokument zu aktivieren.
Siehe auch
Abschnitt betitelt „Siehe auch“- /integrations/artisan/quickstart/
- /integrations/artisan/configuration/
- /integrations/artisan/security-and-operations/
- /integrations/artisan/chrome-renderer-setup/
- /integrations/artisan/troubleshooting/