Artisan in produzione
In sintesi
Sezione intitolata “In sintesi”In produzione, iniettare un renderer configurato e un logger PSR-3, riutilizzare il processo Chrome attivo tra un rendering e l’altro, fornire altezze esplicite per i documenti multi-elemento e delimitare il percorso di rendering con un timeout a monte.
Panoramica concettuale
Sezione intitolata “Panoramica concettuale”BrowserPool mantiene attivo un solo processo Chrome (keepAlive: true) e lo riavvia ogni 100 rendering per limitare la crescita della memoria, un pattern di accumulo noto nei client CDP a lunga durata. Per un worker che esegue il rendering di molti documenti, è preferibile un unico renderer a lunga durata anziché uno per richiesta, in modo da pagare di rado il costo di avvio di Chrome.
Esempio di codice — Produzione
Sezione intitolata “Esempio di codice — Produzione”<?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(); }}Costruire il renderer una sola volta e riutilizzarlo. Chiamare close() all’arresto del worker per rilasciare il processo Chrome in modo deterministico, anziché attendere il distruttore. I due rami catch distinguono un guasto di deployment (runtime mancante) da un guasto in fase di rendering (da ritentare). Non vengono utilizzati blocchi catch vuoti.
Registrarlo in un container come singleton:
$container->singleton(ReportRenderer::class, fn ($c) => new ReportRenderer($c->get(Psr\Log\LoggerInterface::class)));Gestione dell’altezza
Sezione intitolata “Gestione dell’altezza”Quando l’altezza viene omessa, il bridge misura l’altezza del contenuto in Chrome (max delle altezze di scroll e offset di body/document), la converte in punti e aggiunge un buffer di sicurezza di circa 0,2 pollici (~14,4 pt). Il buffer assorbe la differenza tra il layout del viewport di Chrome e il reflow del layout di stampa. Senza di esso, printToPDF può sforare su una seconda pagina che PageImporter (solo pagina 0) ritaglierebbe. Viene imposta un’altezza minima del foglio di 0,1 pollici. I test ChromeHtmlRendererTest::renderUsesAutoFitHeightByDefault, ::renderAutoFitBufferIsAddedNotSubtracted e ::renderAppliesMinimumHeightOf0Point1InchForTinyExplicitHeight verificano questo comportamento.
Per i documenti a layout fisso (fatture, certificati), passare un’altezza esplicita in punti. Quando l’altezza è esplicita, non viene aggiunto alcun buffer e l’output corrisponde esattamente al formato del foglio richiesto (verificato da ::renderHonorsExplicitHeightWithoutAutoBuffer).
Worker batch
Sezione intitolata “Worker batch”- Costruire un renderer per worker; riutilizzarlo.
BrowserPoolriutilizza il browser attivo e si riavvia automaticamente al raggiungimento dei 100 rendering. - Chiamare
close()all’arresto del worker e tra batch di grandi dimensioni se si desidera un nuovo processo Chrome prima del limite dei 100 rendering. - Il distruttore chiama
close(), ma una chiamata esplicita aclose()è deterministica ed è preferibile nei processi a lunga durata. - Gli avvisi di riavvio vengono registrati a livello
noticeinsieme al conteggio dei rendering; impostare un alert in caso di frequenza di riavvio elevata, che indica documenti più pesanti del previsto.
Osservabilità
Sezione intitolata “Osservabilità”Iniettare un logger PSR-3. Eventi emessi e relativi livelli:
| Evento | Livello | Contesto |
|---|---|---|
| Inizio rendering | debug | size, width, height |
| Rendering completato | debug | pdfSize, contentHeight |
| Avvio del browser | info | binary |
| Riavvio del browser | notice | count |
| Chiusura del browser | debug | renderCount |
Non vengono registrati né HTML né byte PDF né testo estratto, in linea con le indicazioni di NIST SP 800-92 sul mantenere i payload fuori dai log operativi. Costruire gli SLO di latenza a partire dalla coppia start/complete e un alert sulla frequenza di riavvio a partire dagli eventi notice.
Pattern di deployment
Sezione intitolata “Pattern di deployment”- Chrome sidecar: eseguire Chrome nello stesso container del worker PHP; impostare
chrome_binary. Effettuare il provisioning di un container in grado di supportare la sandbox — vedere /integrations/artisan/chrome-renderer-setup/. - Senza container / CLI: Artisan non dispone di un container DI. Utilizzare
EInvoiceServiceFactoryper i contratti di fatturazione elettronica Premium nei runner CLI; vedere /integrations/artisan/boot-and-discovery/. - Delimitazione delle risorse: abbinare
render_timeouta un budget di richiesta a monte e a un cgroup/ulimit dell’host. Consultare il modello delle minacce su /integrations/artisan/security-and-operations/.
Casi limite e insidie
Sezione intitolata “Casi limite e insidie”- Un renderer interrotto durante il rendering chiude comunque la pagina Chrome (
finally); il pool rimane utilizzabile. - Il riutilizzo di un singolo renderer tra threads/processes non è supportato; un renderer possiede un solo processo Chrome.
- Il riavvio ogni 100 rendering è fisso; dimensionare i batch tenendone conto per mantenere prevedibili i picchi di latenza.
Prestazioni
Sezione intitolata “Prestazioni”Il costo a regime è dato dal layout dell’input in Chrome più printToPDF, non dall’overhead del bridge. Il costo di avvio è ammortizzato da keepAlive. Prevedere un picco di latenza a ogni centesimo rendering (riavvio del processo) — evidenziarlo negli SLO anziché trattarlo come un incidente.
Note sulla sicurezza
Sezione intitolata “Note sulla sicurezza”I percorsi di produzione sono quelli in cui arriva HTML non attendibile. Rileggere /integrations/artisan/security-and-operations/. Le barriere di rete restano efficaci indipendentemente dalla configurazione, ma no_sandbox: true rimuove l’isolamento del processo Chrome e aumenta il livello di attendibilità richiesto all’input.
Contesto commerciale
Sezione intitolata “Contesto commerciale”Nei worker senza container, EInvoiceServiceFactory restituisce null quando Premium non è installato, quindi il percorso di rendering open source continua a essere eseguito senza modifiche; installare Pro/Enterprise per abilitare l’incorporamento e la convalida della fattura elettronica nel documento generato.
Vedere anche
Sezione intitolata “Vedere anche”- /integrations/artisan/quickstart/
- /integrations/artisan/configuration/
- /integrations/artisan/security-and-operations/
- /integrations/artisan/chrome-renderer-setup/
- /integrations/artisan/troubleshooting/