NextPDF Symfony w produkcji
W skrócie
Dział zatytułowany „W skrócie”Używaj pakietu w długo działających środowiskach uruchomieniowych PHP. Pakiet tworzy niewspółdzielone dokumenty, blokuje rejestr czcionek po rozgrzaniu i resetuje pamięć podręczną obrazów między żądaniami. Duże pliki w formacie PDF (Portable Document Format) strumieniuj, a ciężkie zadania przekazuj do procesów roboczych Messenger.
Cykl życia usług bezpieczny dla procesów roboczych
Dział zatytułowany „Cykl życia usług bezpieczny dla procesów roboczych”Długo działające środowiska uruchomieniowe utrzymują kontener przy życiu między żądaniami, dlatego stan związany z konkretnym żądaniem musi pozostać odizolowany. Procesy robocze FrankenPHP, RoadRunner i Messenger działają zgodnie z tym modelem. Plik services.php pakietu definiuje poniższy cykl życia, zweryfikowany względem definicji usług:
- Document — niewspółdzielony.
nextpdf.document(oraz aliasyPdfDocumentInterface/Document) zwraca nową instancję przy każdym rozwiązaniu. Zgodnie z PSR-11 (PHP Standard Recommendation 11) kontener może prawidłowo zwracać inną wartość przy każdym wywołaniuget()dla tego samego identyfikatora (PSR-11 §1.1.2). Rozwiązuj dokument osobno dla każdego żądania. Nigdy nie przechowuj go między żądaniami. - FontRegistry — współdzielony i zablokowany. Rejestr jest singletonem przez cały czas życia procesu. Po
warmup()(gdypreload_fontsnie jest puste) etap kompilatora wywołujelock(). Blokada zapobiega modyfikacjom w czasie działania oraz zanieczyszczeniu stanu czcionek między żądaniami. - ImageRegistry — współdzielony, resetowany przy każdym żądaniu. Ograniczona pamięć podręczna obrazów według algorytmu najdawniej używanych (LRU) jest współdzielona, ale ma tag
kernel.resetz metodąreset, dzięki czemu Symfony czyści ją między żądaniami w środowiskach uruchomieniowych respektującychkernel.reset. - Kontrakty EInvoice — niewspółdzielone. Gdy dostępne są implementacje Premium, usługi osadzania, walidatora, profilu i schematronu są rejestrowane jako niewspółdzielone. Kontekst parsera pozostaje ograniczony do pojedynczego wywołania i nigdy nie wycieka między żądaniami.
Zalecany wzorzec wstrzykiwania
Dział zatytułowany „Zalecany wzorzec wstrzykiwania”Wstrzyknij PdfFactory, czyli współdzielony, bezstanowy obiekt przechowujący konfigurację, i wywołuj create() osobno dla każdego żądania:
public function __construct(private readonly PdfFactory $pdf) {}
public function action(): Response{ $doc = $this->pdf->create(); // fresh, disposable // ... build ... return PdfResponse::inline($doc, 'document.pdf');}Nie wstrzykuj Document ani nextpdf.document do współdzielonej usługi przechowywanej między żądaniami. Zamiast tego rozwiązuj je wewnątrz metody o zasięgu żądania.
Strumieniowanie dużych dokumentów
Dział zatytułowany „Strumieniowanie dużych dokumentów”PdfResponse::streamDownload() i streamInline() zwracają obiekt StreamedResponse. Wywołanie zwrotne emituje treść PDF w porcjach po 64 KB i opróżnia bufor po każdej z nich, co ogranicza rozmiar bufora odpowiedzi dla dużych dokumentów. Poniższe zachowania zostały zweryfikowane względem PdfResponse:
- Warianty strumieniowe celowo pomijają nagłówek
Content-Length, ponieważ obiekt odpowiedzi nie zna z góry rozmiaru treści. Paski postępu pobierania i niektóre serwery proxy działają lepiej przy znanej długości. Użyj niestrumieniowychdownload()lubinline(), gdy dokument jest na tyle mały, że mieści się w pamięci, a znana długość treści jest pożądana. - Warianty strumieniowe emitują te same nagłówki bezpieczeństwa oraz ten sam
Cache-Control: private, max-age=0, must-revalidateco warianty buforowane.
Wybieraj strumieniowanie dla wielomegabajtowych raportów i eksportów wsadowych. Warianty buforowane wybieraj dla małych odpowiedzi wrażliwych na opóźnienia.
Generowanie asynchroniczne na dużą skalę
Dział zatytułowany „Generowanie asynchroniczne na dużą skalę”Przekazuj generowanie do Messenger, gdy żądania muszą szybko zwracać odpowiedź albo renderowanie obciąża procesor.
- Zaimplementuj
PdfBuilderInterfacedla każdego typu dokumentu. - Zarejestruj buildery w
container.service_locatori podłącz go jako$builderLocatorobiektuGeneratePdfHandler. - Skieruj
GeneratePdfMessagedo trwałego transportu. - Uruchamiaj procesy robocze z ograniczonym czasem życia.
Ograniczony czas życia procesu roboczego
Dział zatytułowany „Ograniczony czas życia procesu roboczego”Odświeżaj procesy robocze, aby wyciek pamięci w zależności zewnętrznej nie mógł rosnąć bez ograniczeń:
php bin/console messenger:consume async \ --limit=200 \ --memory-limit=256M \ --time-limit=3600Klucze konfiguracyjne pakietu messenger.timeout i messenger.retries zapisują zamierzony limit czasu na wiadomość oraz budżet ponownych prób. Wymuś takie samo zachowanie za pomocą strategii ponawiania Symfony oraz flag procesu roboczego.
Bezpieczeństwo ścieżki wyjściowej w procesach roboczych
Dział zatytułowany „Bezpieczeństwo ścieżki wyjściowej w procesach roboczych”GeneratePdfMessage weryfikuje ścieżkę wyjściową podczas konstruowania. GeneratePdfHandler weryfikuje ją ponownie w czasie wykonania, przed zapisem na dysk. Ta dwuetapowa kontrola ma znaczenie w pracy asynchronicznej. Wiadomość może pozostawać w kolejce między wysłaniem a odebraniem, dlatego handler nie ufa ślepo ścieżce z kolejki. Ogranicz uprawnienia systemu plików procesu roboczego do zamierzonego katalogu wyjściowego jako element obrony w głąb.
Obserwowalność
Dział zatytułowany „Obserwowalność”Usługi FontRegistry i ImageRegistry przyjmują opcjonalny Psr\Log\LoggerInterface (powiązany przez nullOnInvalid()). Gdy aplikacja dostarcza logger, rejestry mogą emitować za jego pośrednictwem dane diagnostyczne. Logger jest opcjonalnym, wymiennym współpracownikiem zgodnym z kontraktem loggera PSR-3 (PSR-3). Aby uzyskać widoczność na poziomie żądania, dodaj logowanie wokół PdfFactory::create() oraz handlera Messenger w kodzie aplikacji. Podczas analizy incydentów używaj messenger:consume -vv.
Lista kontrolna wdrożenia
Dział zatytułowany „Lista kontrolna wdrożenia”- Przypnij jedną wersję główną
nextpdf/corew plikucomposer.jsonaplikacji (pakiet akceptuje^3.0 || ^5.2). - Upewnij się, że
ext-mbstringiext-zlibsą włączone we wdrożonym obrazie PHP (w przeciwnym razie pakiet zawodzi natychmiast przy starcie). - Wstępnie wypełnij
preload_fontsczcionkami, których używają dokumenty, aby rejestr rozgrzewał się i blokował przy starcie, a nie przy pierwszym żądaniu. - Ustaw
cache_pathna zapisywalną, trwałą lokalizację, jeśli polegasz na artefaktach z pamięci podręcznej między wdrożeniami. W przeciwnym razie domyślna wartość%kernel.cache_dir%jest wystarczająca. - Uruchom
php bin/console cache:warmuppodczas wdrażania, aby skompilowany kontener (w tym sondy opcjonalnych rozszerzeń) został zbudowany przed napływem ruchu. - Używaj trwałego transportu Messenger (nie
sync) do produkcyjnej pracy asynchronicznej i odświeżaj procesy robocze za pomocą--limit/--memory-limit/--time-limit.
Przypadki brzegowe i pułapki
Dział zatytułowany „Przypadki brzegowe i pułapki”- Odpowiedzi strumieniowe za buforującym serwerem proxy — serwer proxy buforujący całą treść niweczy korzyść pamięciową. Skonfiguruj serwer proxy tak, aby strumieniował odpowiedzi PDF, albo użyj tam odpowiedzi buforowanych.
kernel.resetnieobsługiwany — w środowisku uruchomieniowym, które nie wywołujekernel.reset, pamięć podręczna obrazów jest ograniczona przezimage_cache_mb, ale nie jest czyszczona między żądaniami; odpowiednio dobierz limit.- Przechowywanie dokumentu między żądaniami — przechwycony
Documentz wcześniejszego żądania będzie zawierał nieaktualny stan. Zawsze rozwiązuj go osobno dla każdego żądania za pomocąPdfFactory.
Zgodność
Dział zatytułowany „Zgodność”Każdy wiersz jest normatywnym stwierdzeniem na tej stronie, przypiętym do pełnego 64-znakowego szesnastkowego reference_id z bramkowanego korpusu organizacji opracowującej standardy (SDO). Pochodzenie manifestu korpusu i transportu pobierania znajduje się w _sidecars/rag-citations.yaml.
| Specyfikacja | Klauzula | reference_id | Stwierdzenie |
|---|---|---|---|
| PSR-11 | psr_11_container#1.1.2.p3.b | Usługa niewspółdzielona: odrębna wartość przy każdym rozwiązaniu | |
| PSR-3 | psr_3_logger#x3.p17 | Opcjonalny współpracownik typu logger |
Zobacz także
Dział zatytułowany „Zobacz także”- /integrations/symfony/configuration/ — cykl życia usług i parametry.
- /integrations/symfony/security-and-operations/ — nagłówki odpowiedzi, walidacja ścieżek, obsługa kluczy.
- /integrations/symfony/troubleshooting/ — diagnostyka startu i czasu działania.
- /integrations/symfony/quickstart/ — minimalna konfiguracja asynchroniczna.