Ga naar inhoud

Artisan in productie

Injecteer in productie een geconfigureerde renderer en een PHP Standards Recommendation 3 (PSR-3) logger, hergebruik het actieve Chrome-proces tussen renders, stel expliciete hoogtes in voor documenten met meerdere elementen en begrens het renderpad met een upstream-time-out.

BrowserPool houdt één Chrome-proces actief (keepAlive: true) en herstart het om de 100 renders om geheugengroei te beperken; dat is een bekend accumulatiepatroon bij langlevende Chrome DevTools Protocol (CDP) clients. Gebruik voor een worker die veel documenten rendert één langlevende renderer in plaats van één renderer per aanvraag, zodat je de opstartkosten van Chrome maar zelden betaalt.

render-service.php
<?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();
}
}

Maak de renderer één keer aan en hergebruik deze daarna. Roep close() aan wanneer de worker wordt afgesloten, zodat het Chrome-proces deterministisch wordt vrijgegeven in plaats van te wachten op de destructor. De twee catch-takken scheiden een deployment-fout (ontbrekende runtime) van een fout tijdens het renderen (opnieuw te proberen). Gebruik geen lege catch-blokken.

Registreer deze als singleton in een container:

$container->singleton(ReportRenderer::class, fn ($c) =>
new ReportRenderer($c->get(Psr\Log\LoggerInterface::class)));

Wanneer je de hoogte weglaat, meet de bridge de inhoudshoogte in Chrome (max van de scroll- en offsethoogtes van body/document), zet deze om naar punten en voegt een veiligheidsbuffer van ~0,2 inch (~14,4 pt) toe. De buffer overbrugt het verschil tussen de viewport-lay-out van Chrome en de reflow van de afdruk-lay-out. Zonder die buffer kan printToPDF inhoud doorschuiven naar een tweede pagina die PageImporter (alleen pagina 0) zou afkappen. De bridge dwingt een minimale papierhoogte van 0,1 inch af. De tests ChromeHtmlRendererTest::renderUsesAutoFitHeightByDefault, ::renderAutoFitBufferIsAddedNotSubtracted en ::renderAppliesMinimumHeightOf0Point1InchForTinyExplicitHeight verifiëren dit gedrag.

Geef voor documenten met een vaste lay-out (facturen, certificaten) een expliciete hoogte in punten op. Als de hoogte expliciet is, wordt er geen buffer toegevoegd en komt de uitvoer exact overeen met het gevraagde papierformaat (geverifieerd door ::renderHonorsExplicitHeightWithoutAutoBuffer).

  • Maak per worker één renderer aan en hergebruik deze. BrowserPool hergebruikt de actieve browser en herstart automatisch op de grens van 100 renders.
  • Roep close() aan bij het afsluiten van de worker en tussen grote batches wanneer je vóór de grens van 100 renders al een vers Chrome-proces wilt.
  • De destructor roept close() aan, maar een expliciete aanroep van close() is deterministisch en heeft de voorkeur in langlopende processen.
  • Herstartmeldingen worden op notice-niveau gelogd met het aantal renders; stel een alert in op een verhoogd herstartpercentage, omdat dit wijst op zwaardere documenten dan verwacht.

Injecteer een PSR-3 logger. De renderer logt de volgende events op deze niveaus:

EventNiveauContext
Render startdebugsize, width, height
Render voltooiddebugpdfSize, contentHeight
Browser gestartinfobinary
Browser herstartnoticecount
Browser geslotendebugrenderCount

Er wordt geen HTML, geen PDF-bytes en geen geëxtraheerde tekst gelogd. Zo blijven payloads buiten de operationele logs en sluit de logging aan op de richtlijnen voor logcontent uit National Institute of Standards and Technology Special Publication (NIST SP) 800-92. Baseer latency service-level objectives (SLO’s) op het start/complete-paar en bouw een alert voor het herstartpercentage op basis van de notice-events.

  • Sidecar Chrome: draai Chrome in dezelfde container als de PHP-worker; pin chrome_binary vast. Gebruik een container die geschikt is voor sandboxing; zie /integrations/artisan/chrome-renderer-setup/.
  • Containerless / CLI: Artisan heeft geen dependency injection container. Gebruik EInvoiceServiceFactory voor Premium e-invoice-contracten in command-line interface (CLI) runners; zie /integrations/artisan/boot-and-discovery/.
  • Resource bounding: combineer render_timeout met een upstream-aanvraagbudget en een host-cgroup/ulimit. Zie het dreigingsmodel op /integrations/artisan/security-and-operations/.
  • Een renderer die tijdens een render wordt onderbroken, sluit toch de Chrome-pagina (finally), en de pool blijft bruikbaar.
  • Eén renderer hergebruiken over meerdere threads/processes wordt niet ondersteund; één renderer bezit één Chrome-proces.
  • De herstart na 100 renders ligt vast; stem de batchgrootte hierop af zodat latencypieken voorspelbaar blijven.

De steady-state-kosten bestaan uit de Chrome-lay-out van de invoer plus printToPDF, niet uit overhead van de bridge. keepAlive spreidt de opstartkosten over de renders. Verwacht een latencypiek bij elke 100ste render (procesherstart); maak deze zichtbaar in de SLO’s in plaats van deze als incident te behandelen.

Productiepaden verwerken niet-vertrouwde HTML. Lees /integrations/artisan/security-and-operations/ opnieuw. De netwerkbarrières blijven van kracht ongeacht de configuratie, maar no_sandbox: true verwijdert de procesisolatie van Chrome en verhoogt de vertrouwenseis voor de invoer.

In containerless workers retourneert EInvoiceServiceFactory de waarde null wanneer Premium niet is geïnstalleerd, zodat het open-source-renderpad ongewijzigd blijft. Installeer Pro/Enterprise om e-invoices in het gerenderde document te kunnen inbedden en valideren.

  • /integrations/artisan/quickstart/
  • /integrations/artisan/configuration/
  • /integrations/artisan/security-and-operations/
  • /integrations/artisan/chrome-renderer-setup/
  • /integrations/artisan/troubleshooting/