NextPDF Symfony di lingkungan produksi
Gambaran umum
Bagian berjudul “Gambaran umum”Gunakan bundle ini pada runtime PHP yang berjalan lama. Bundle ini membuat dokumen non-shared, mengunci registry fon setelah warmup, dan mereset cache gambar di antara permintaan. Gunakan streaming untuk berkas Portable Document Format (PDF) berukuran besar, dan alihkan tugas berat ke worker Messenger.
Siklus hidup layanan yang aman untuk worker
Bagian berjudul “Siklus hidup layanan yang aman untuk worker”Runtime yang berjalan lama menjaga container tetap hidup lintas permintaan, sehingga state per permintaan harus tetap terisolasi. Worker FrankenPHP, RoadRunner, dan Messenger mengikuti model ini. Berkas services.php pada bundle mendefinisikan siklus hidup berikut, yang diverifikasi terhadap definisi layanan:
- Document — non-shared.
nextpdf.document(beserta aliasPdfDocumentInterface/Document) menghasilkan instance baru pada setiap resolusi. Berdasarkan PSR-11 (PHP Standard Recommendation 11), container secara sah dapat mengembalikan nilai yang berbeda untuk setiapget()pada id yang sama (PSR-11 §1.1.2). Resolusikan dokumen per permintaan. Jangan pernah menyimpannya lintas permintaan. - FontRegistry — shared dan terkunci. Registry ini adalah singleton selama masa hidup proses. Setelah
warmup()(ketikapreload_fontstidak kosong), compiler pass memanggillock(). Penguncian ini mencegah mutasi saat runtime dan kontaminasi state fon lintas permintaan. - ImageRegistry — shared, direset per permintaan. Cache gambar least recently used (LRU) yang terbatas bersifat shared, tetapi diberi tag
kernel.resetdengan metodereset, sehingga Symfony membersihkannya di antara permintaan pada runtime yang menghormatikernel.reset. - Kontrak EInvoice — non-shared. Ketika implementasi Premium tersedia, layanan embedder, validator, profile, dan schematron didaftarkan sebagai non-shared. Konteks parser tetap dibatasi pada setiap pemanggilan dan tidak pernah bocor lintas permintaan.
Pola injeksi yang direkomendasikan
Bagian berjudul “Pola injeksi yang direkomendasikan”Injeksikan PdfFactory, yaitu penampung konfigurasi yang shared dan stateless, lalu panggil create() per permintaan:
public function __construct(private readonly PdfFactory $pdf) {}
public function action(): Response{ $doc = $this->pdf->create(); // fresh, disposable // ... build ... return PdfResponse::inline($doc, 'document.pdf');}Jangan menginjeksikan Document atau nextpdf.document ke dalam layanan shared yang disimpan lintas permintaan. Sebagai gantinya, resolusikan di dalam metode yang cakupannya dibatasi pada permintaan.
Streaming dokumen besar
Bagian berjudul “Streaming dokumen besar”PdfResponse::streamDownload() dan streamInline() mengembalikan StreamedResponse. Callback memancarkan body PDF dalam potongan 64 KB dan melakukan flush setelah setiap potongan, sehingga buffer respons tetap terbatas untuk dokumen besar. Perilaku di bawah ini diverifikasi terhadap PdfResponse:
- Varian streaming sengaja menghilangkan
Content-Lengthkarena objek respons tidak mengetahui ukuran body sejak awal. Bilah kemajuan unduhan dan beberapa proxy bekerja lebih baik dengan panjang yang diketahui. Gunakandownload()atauinline()non-streaming ketika dokumen cukup kecil untuk disimpan di memori dan panjang konten diperlukan. - Varian streaming memancarkan header keamanan yang sama serta
Cache-Control: private, max-age=0, must-revalidateyang sama seperti varian buffered.
Pilih streaming untuk laporan berukuran beberapa megabita dan ekspor batch. Pilih varian buffered untuk respons kecil yang sensitif terhadap latensi.
Pembuatan asinkron dalam skala besar
Bagian berjudul “Pembuatan asinkron dalam skala besar”Alihkan proses pembuatan ke Messenger ketika permintaan harus segera dikembalikan, atau ketika rendering banyak menggunakan prosesor.
- Implementasikan
PdfBuilderInterfaceuntuk setiap jenis dokumen. - Daftarkan builder di dalam
container.service_locatordan hubungkan sebagai$builderLocatorpadaGeneratePdfHandler. - Arahkan
GeneratePdfMessageke transport yang durable. - Jalankan worker dengan masa hidup yang terbatas.
Masa hidup worker yang terbatas
Bagian berjudul “Masa hidup worker yang terbatas”Daur ulang worker agar alokasi yang bocor di dependensi pihak ketiga tidak dapat tumbuh tanpa batas:
php bin/console messenger:consume async \ --limit=200 \ --memory-limit=256M \ --time-limit=3600Kunci konfigurasi messenger.timeout dan messenger.retries pada bundle mencatat timeout per pesan dan anggaran percobaan ulang yang dimaksudkan. Terapkan perilaku yang sama melalui strategi percobaan ulang Symfony dan flag worker.
Keamanan jalur keluaran pada worker
Bagian berjudul “Keamanan jalur keluaran pada worker”GeneratePdfMessage memvalidasi jalur keluaran pada saat konstruksi. GeneratePdfHandler memvalidasinya kembali pada saat eksekusi, sebelum menulis ke disk. Pemeriksaan dua tahap ini penting untuk pekerjaan asinkron. Sebuah pesan dapat berada dalam antrean antara pengiriman dan konsumsi, sehingga handler tidak mempercayai jalur yang diantrekan secara membuta. Batasi izin sistem berkas worker pada direktori keluaran yang dimaksud sebagai pertahanan berlapis.
Observabilitas
Bagian berjudul “Observabilitas”Layanan FontRegistry dan ImageRegistry menerima Psr\Log\LoggerInterface opsional (di-bind dengan nullOnInvalid()). Ketika aplikasi menyediakan logger, registry dapat memancarkan diagnostik melaluinya. Logger adalah kolaborator opsional yang dapat ditukar berdasarkan kontrak logger PSR-3 (PSR-3). Untuk visibilitas tingkat permintaan, catat log di sekitar PdfFactory::create() dan handler Messenger di dalam kode aplikasi Anda. Gunakan messenger:consume -vv selama triase insiden.
Daftar periksa deployment
Bagian berjudul “Daftar periksa deployment”- Sematkan satu versi mayor
nextpdf/coredicomposer.jsonaplikasi (bundle menerima^3.0 || ^5.2). - Pastikan
ext-mbstringdanext-zlibdiaktifkan dalam image PHP yang di-deploy (jika tidak, bundle gagal lebih awal saat boot). - Isi
preload_fontsterlebih dahulu dengan fon yang digunakan dokumen Anda agar registry melakukan warmup dan mengunci saat boot, bukan pada permintaan pertama. - Arahkan
cache_pathke lokasi yang dapat ditulis dan persisten jika Anda mengandalkan artefak yang di-cache lintas deploy. Jika tidak, nilai default%kernel.cache_dir%sudah memadai. - Jalankan
php bin/console cache:warmupsaat deploy agar container yang dikompilasi (termasuk probe ekstensi opsional) dibangun sebelum lalu lintas masuk. - Gunakan transport Messenger yang durable (bukan
sync) untuk pekerjaan asinkron produksi, dan daur ulang worker dengan--limit/--memory-limit/--time-limit.
Kasus tepi dan jebakan
Bagian berjudul “Kasus tepi dan jebakan”- Respons streaming di balik proxy yang melakukan buffering — Proxy yang melakukan buffering pada seluruh body meniadakan manfaat memori. Konfigurasikan proxy untuk melakukan streaming respons PDF, atau gunakan respons buffered dalam kondisi tersebut.
kernel.resettidak dihormati — Pada runtime yang tidak memanggilkernel.reset, cache gambar dibatasi olehimage_cache_mbtetapi tidak dibersihkan di antara permintaan; tentukan ukuran batas sesuai kebutuhan.- Menyimpan dokumen lintas permintaan —
Documentyang ditangkap dari permintaan sebelumnya akan membawa state yang usang. Selalu resolusikan per permintaan melaluiPdfFactory.
Kesesuaian
Bagian berjudul “Kesesuaian”Setiap baris merupakan klaim normatif pada halaman ini, ditambatkan ke reference_id 64-heksadesimal lengkap dari korpus standards development organization (SDO) yang terkunci. Provenans untuk manifest korpus dan transport pengambilan berada di _sidecars/rag-citations.yaml.
| Spesifikasi | Klausa | reference_id | Klaim |
|---|---|---|---|
| PSR-11 | psr_11_container#1.1.2.p3.b | Layanan non-shared: nilai berbeda per resolusi | |
| PSR-3 | psr_3_logger#x3.p17 | Kolaborator logger opsional |
Lihat juga
Bagian berjudul “Lihat juga”- /integrations/symfony/configuration/ — siklus hidup layanan dan parameter.
- /integrations/symfony/security-and-operations/ — header respons, validasi jalur, penanganan kunci.
- /integrations/symfony/troubleshooting/ — diagnostik boot dan runtime.
- /integrations/symfony/quickstart/ — penyiapan asinkron minimal.