Lewati ke konten

NextPDF Symfony di lingkungan produksi

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.

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 alias PdfDocumentInterface / Document) menghasilkan instance baru pada setiap resolusi. Berdasarkan PSR-11 (PHP Standard Recommendation 11), container secara sah dapat mengembalikan nilai yang berbeda untuk setiap get() 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() (ketika preload_fonts tidak kosong), compiler pass memanggil lock(). 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.reset dengan metode reset, sehingga Symfony membersihkannya di antara permintaan pada runtime yang menghormati kernel.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.

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.

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-Length karena objek respons tidak mengetahui ukuran body sejak awal. Bilah kemajuan unduhan dan beberapa proxy bekerja lebih baik dengan panjang yang diketahui. Gunakan download() atau inline() 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-revalidate yang sama seperti varian buffered.

Pilih streaming untuk laporan berukuran beberapa megabita dan ekspor batch. Pilih varian buffered untuk respons kecil yang sensitif terhadap latensi.

Alihkan proses pembuatan ke Messenger ketika permintaan harus segera dikembalikan, atau ketika rendering banyak menggunakan prosesor.

  1. Implementasikan PdfBuilderInterface untuk setiap jenis dokumen.
  2. Daftarkan builder di dalam container.service_locator dan hubungkan sebagai $builderLocator pada GeneratePdfHandler.
  3. Arahkan GeneratePdfMessage ke transport yang durable.
  4. Jalankan worker dengan masa hidup yang terbatas.

Daur ulang worker agar alokasi yang bocor di dependensi pihak ketiga tidak dapat tumbuh tanpa batas:

Terminal window
php bin/console messenger:consume async \
--limit=200 \
--memory-limit=256M \
--time-limit=3600

Kunci 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.

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.

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.

  • Sematkan satu versi mayor nextpdf/core di composer.json aplikasi (bundle menerima ^3.0 || ^5.2).
  • Pastikan ext-mbstring dan ext-zlib diaktifkan dalam image PHP yang di-deploy (jika tidak, bundle gagal lebih awal saat boot).
  • Isi preload_fonts terlebih dahulu dengan fon yang digunakan dokumen Anda agar registry melakukan warmup dan mengunci saat boot, bukan pada permintaan pertama.
  • Arahkan cache_path ke 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:warmup saat 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.
  • 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.reset tidak dihormati — Pada runtime yang tidak memanggil kernel.reset, cache gambar dibatasi oleh image_cache_mb tetapi tidak dibersihkan di antara permintaan; tentukan ukuran batas sesuai kebutuhan.
  • Menyimpan dokumen lintas permintaanDocument yang ditangkap dari permintaan sebelumnya akan membawa state yang usang. Selalu resolusikan per permintaan melalui PdfFactory.

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.

SpesifikasiKlausareference_idKlaim
PSR-11psr_11_container#1.1.2.p3.bLayanan non-shared: nilai berbeda per resolusi
PSR-3psr_3_logger#x3.p17Kolaborator logger opsional
  • /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.