Artisan w środowisku produkcyjnym
W skrócie
Dział zatytułowany „W skrócie”W środowisku produkcyjnym wstrzykuj skonfigurowany renderer oraz rejestrator zgodny z PHP Standards Recommendation 3 (PSR-3), ponownie wykorzystuj działający proces Chrome między renderowaniami, ustawiaj jawne wysokości dla dokumentów wieloelementowych i obejmuj ścieżkę renderowania nadrzędnym limitem czasu.
Przegląd koncepcyjny
Dział zatytułowany „Przegląd koncepcyjny”Klasa BrowserPool utrzymuje przy życiu jeden proces Chrome (keepAlive: true) i uruchamia go ponownie co 100 renderowań, aby ograniczyć narastanie zużycia pamięci — znany wzorzec w długo działających klientach Chrome DevTools Protocol (CDP). W procesie renderującym wiele dokumentów używaj jednego długo działającego renderera zamiast osobnego renderera dla każdego żądania, aby koszt uruchomienia Chrome ponosić tylko sporadycznie.
Przykład kodu — środowisko produkcyjne
Dział zatytułowany „Przykład kodu — środowisko produkcyjne”<?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(); }}Utwórz renderer raz, a potem używaj go ponownie. Wywołaj close() podczas zamykania procesu roboczego, aby deterministycznie zwolnić proces Chrome, zamiast czekać na destruktor. Dwa bloki catch rozdzielają błąd wdrożenia (brak środowiska uruchomieniowego) od błędu czasu renderowania (możliwego do ponowienia). Nie używaj pustych bloków catch.
Zarejestruj go w kontenerze jako singleton:
$container->singleton(ReportRenderer::class, fn ($c) => new ReportRenderer($c->get(Psr\Log\LoggerInterface::class)));Obsługa wysokości
Dział zatytułowany „Obsługa wysokości”Gdy pominiesz wysokość, most mierzy wysokość treści w Chrome (max wysokości przewijania i przesunięcia dla body/document), przelicza ją na punkty i dodaje bufor bezpieczeństwa wynoszący ~0,2 cala (~14,4 pt). Bufor kompensuje różnicę między układem widoku Chrome a przepływem układu wydruku. Bez niego printToPDF może przenieść część treści na drugą stronę, którą PageImporter (tylko strona 0) by przyciął. Most wymusza minimalną wysokość strony wynoszącą 0,1 cala. Potwierdzają to testy ChromeHtmlRendererTest::renderUsesAutoFitHeightByDefault, ::renderAutoFitBufferIsAddedNotSubtracted oraz ::renderAppliesMinimumHeightOf0Point1InchForTinyExplicitHeight.
Dla dokumentów o stałym układzie (faktury, certyfikaty) przekaż jawną wysokość w punktach. Gdy wysokość jest jawna, nie jest dodawany żaden bufor, a wynik dokładnie odpowiada żądanemu rozmiarowi strony (co potwierdza test ::renderHonorsExplicitHeightWithoutAutoBuffer).
Procesy wsadowe
Dział zatytułowany „Procesy wsadowe”- Utwórz jeden renderer na proces roboczy i używaj go ponownie.
BrowserPoolkorzysta z działającej przeglądarki i automatycznie uruchamia ją ponownie na granicy 100 renderowań. - Wywołaj
close()przy zamykaniu procesu roboczego oraz między dużymi partiami, gdy chcesz uzyskać świeży proces Chrome wcześniej niż na granicy 100 renderowań. - Destruktor wywołuje
close(), ale jawneclose()jest deterministyczne i preferowane w procesach długo działających. - Powiadomienia o ponownym uruchomieniu są zapisywane na poziomie
noticewraz z liczbą renderowań; ustaw alert na podwyższoną częstość ponownych uruchomień, ponieważ wskazuje ona na dokumenty cięższe niż oczekiwano.
Obserwowalność
Dział zatytułowany „Obserwowalność”Wstrzyknij rejestrator PSR-3. Renderer emituje następujące zdarzenia i poziomy:
| Zdarzenie | Poziom | Kontekst |
|---|---|---|
| Początek renderowania | debug | size, width, height |
| Renderowanie zakończone | debug | pdfSize, contentHeight |
| Uruchomienie przeglądarki | info | binary |
| Ponowne uruchomienie przeglądarki | notice | count |
| Zamknięcie przeglądarki | debug | renderCount |
Nie są rejestrowane żadne dane HTML, bajty PDF ani wyodrębniony tekst. Dzięki temu ładunki danych nie trafiają do dzienników operacyjnych, co jest zgodne z wytycznymi dotyczącymi zawartości dzienników z publikacji National Institute of Standards and Technology Special Publication (NIST SP) 800-92. Zdefiniuj cele poziomu usług (SLO) dla opóźnień na podstawie pary zdarzeń start/complete oraz utwórz alert dla częstości ponownych uruchomień na podstawie zdarzeń notice.
Wzorce wdrażania
Dział zatytułowany „Wzorce wdrażania”- Chrome jako sidecar: uruchom Chrome w tym samym kontenerze co proces roboczy PHP; przypnij
chrome_binary. Przygotuj kontener obsługujący piaskownicę; zobacz /integrations/artisan/chrome-renderer-setup/. - Bez kontenera / CLI: Artisan nie ma kontenera wstrzykiwania zależności. W środowiskach uruchomieniowych interfejsu wiersza poleceń (CLI) użyj
EInvoiceServiceFactorydla kontraktów e-faktur w wersji Premium; zobacz /integrations/artisan/boot-and-discovery/. - Ograniczanie zasobów: połącz
render_timeoutz nadrzędnym budżetem żądań oraz mechanizmami hosta cgroup/ulimit. Zapoznaj się z modelem zagrożeń na /integrations/artisan/security-and-operations/.
Przypadki brzegowe i pułapki
Dział zatytułowany „Przypadki brzegowe i pułapki”- Renderer przerwany w trakcie renderowania nadal zamyka stronę Chrome (
finally), a pula pozostaje zdatna do użytku. - Ponowne wykorzystanie jednego renderera między różnymi wątkami/procesami (threads/processes) nie jest obsługiwane; jeden renderer jest właścicielem jednego procesu Chrome.
- Ponowne uruchomienie co 100 renderowań jest stałe; dobieraj rozmiar partii z myślą o nim, aby skoki opóźnień pozostawały przewidywalne.
Wydajność
Dział zatytułowany „Wydajność”W stanie ustalonym główny koszt to zbudowanie układu danych wejściowych w Chrome plus printToPDF, a nie narzut mostu. keepAlive rozkłada koszt uruchomienia na kolejne renderowania. Spodziewaj się skoku opóźnień przy co setnym renderowaniu (ponowne uruchomienie procesu); uwzględnij go w SLO zamiast traktować jako incydent.
Uwagi dotyczące bezpieczeństwa
Dział zatytułowany „Uwagi dotyczące bezpieczeństwa”Do ścieżek produkcyjnych trafia niezaufany kod HTML. Przeczytaj ponownie /integrations/artisan/security-and-operations/. Bariery sieciowe obowiązują niezależnie od konfiguracji, ale no_sandbox: true usuwa izolację procesu Chrome i zwiększa wymagany poziom zaufania do danych wejściowych.
Kontekst komercyjny
Dział zatytułowany „Kontekst komercyjny”W procesach roboczych bez kontenera EInvoiceServiceFactory zwraca null, gdy wersja Premium nie jest zainstalowana, dzięki czemu ścieżka renderowania open source działa bez zmian. Zainstaluj wersję Pro/Enterprise, aby włączyć osadzanie i walidację e-faktur w renderowanym dokumencie.
Zobacz także
Dział zatytułowany „Zobacz także”- /integrations/artisan/quickstart/
- /integrations/artisan/configuration/
- /integrations/artisan/security-and-operations/
- /integrations/artisan/chrome-renderer-setup/
- /integrations/artisan/troubleshooting/