Vì sao engine PDF của bạn thuộc về PHP, không phải một sidecar
Spec: ISO/IEC 25010:2023, §3.7ISO/IEC 25010:2023 §3.7Spec: ISO 32000-2, §7ISO 32000-2 §7
Tổng quan nhanh
Phần tiêu đề “Tổng quan nhanh”Có hai nơi một PDF có thể được tạo ra: bên trong tiến trình PHP của bạn, hoặc một chỗ nào khác mà bạn phải vận hành. NextPDF tạo nó bên trong. Trang này là lập luận cho lựa chọn đó — vì sao một engine in-process thường là mặc định đúng, và mô hình “một chỗ nào khác” thực sự tốn những gì một khi nó vào production.
Đây là góc kiến trúc, không phải góc framework. Cách cùng một engine vươn tới Laravel, Symfony, CodeIgniter và mã standalone là một câu chuyện khác, được kể trong one engine, every framework.
Vì sao điều này quan trọng
Phần tiêu đề “Vì sao điều này quan trọng”Một tính năng PDF hiếm khi bắt đầu như một hệ thống bạn phải vận hành. Nó bắt đầu như một dòng trong một controller: kết xuất hóa đơn này, trả về báo cáo kia. Mô hình sidecar biến dòng đó thành hạ tầng. Để vẽ tài liệu, giờ bạn phải chạy một thứ thứ hai — một binary bên ngoài, một trình duyệt headless, một microservice riêng — và mọi thứ thứ hai đó cần cũng trở thành vấn đề của bạn: phiên bản của nó, bộ nhớ của nó, container của nó, mạng của nó, các chế độ lỗi của nó, cú gọi trực của nó lúc 2 giờ sáng.
Chi phí ấy vô hình trên bản demo và không thể tránh trong production. Một engine tài liệu sống trong tiến trình của bạn thì chẳng có chi phí nào trong số đó. Câu hỏi không phải “một sidecar có tạo được PDF không” — tất nhiên là được. Nó là “bạn đã đăng ký vận hành những gì để đạt tới đó, và bạn có cần phải thế không.”
Tóm tắt ngắn gọn
Phần tiêu đề “Tóm tắt ngắn gọn”- In-process nghĩa là không có runtime thứ hai. NextPDF vẽ PDF bên trong cùng một PHP worker đã xử lý request. Không có subprocess để sinh ra, không có service để triển khai, và chẳng có gì thêm phải giữ cho sống.
- Một sidecar thêm vào một bề mặt vận hành mà bạn vốn không có. Một trình duyệt đóng gói kèm hay một binary bên ngoài mang theo phiên bản riêng, dấu chân bảo mật riêng, và container riêng — tất cả những thứ bạn giờ phải vá và giám sát.
- Các ranh giới tiến trình là nơi mọi thứ trục trặc. Khởi động nguội, timeout, đường ống liên-tiến-trình mong manh, và dữ liệu rời khỏi tiến trình của bạn là những chế độ lỗi mà một cú gọi in-process đơn giản là không có.
- In-process kiểm thử được và xác định. Engine là PHP có kiểu mà bạn có thể unit-test, mock, và suy luận về nó — chứ không phải một renderer mờ đục mà bạn chỉ có thể dò bằng cách chạy nó rồi nhìn đầu ra.
- Một trình duyệt thật vẫn có những công dụng thật. Để kết xuất trung thực đến từng điểm ảnh các trang web hiện đại tùy ý, một trình duyệt headless là công cụ trung thực — và NextPDF có thể ủy thác cho một cái như vậy một cách có chủ đích. Đó là một đường nối, không phải mặc định.
Cách NextPDF tiếp cận điều này
Phần tiêu đề “Cách NextPDF tiếp cận điều này”Hãy đặt hai kiến trúc cạnh nhau. Đường in-process là một cú gọi hàm. Đường sidecar là một hệ thống phân tán thu nhỏ — và mỗi mũi tên giữa các hộp của nó là một chỗ thất bại độc lập với mã của bạn.
- In-process: call the enginewriteHtml() or the document API runs inside the current PHP worker — no subprocess, no socket.
- In-process: receive PDF bytesThe engine returns native PDF content directly; nothing left the process.
- Sidecar: serialize and shipMarkup or a request is marshalled out of your process to a binary, browser, or remote service.
- Sidecar: cross the boundaryA process spawn or network hop — with a cold start, a timeout, and an IPC contract that can break.
- Sidecar: run a second runtimeAn external renderer with its own version, memory profile, and security surface to operate and patch.
- Sidecar: deserialize backMarshal the result back in and translate the renderer’s errors into yours.
Không có runtime thứ hai để vận hành. Mô hình sidecar là hai hệ thống khoác
lên bộ trang phục của một tính năng. Một wkhtmltopdf đóng gói kèm, một service
Chromium headless, một microservice kết xuất riêng — mỗi cái là một runtime với
nhịp phát hành riêng và các lỗi riêng. Bạn thừa kế toàn bộ. Engine in-process
được giao như một phụ thuộc Composer; nó được nâng cấp theo cách mọi thư viện
khác trong composer.json của bạn được nâng cấp, không thêm daemon, image, hay
socket nào vào quá trình triển khai của bạn.
Trôi phiên bản và một bề mặt bảo mật rộng hơn. Một trình duyệt đóng gói kèm là một codebase lớn, chuyển động nhanh với một dòng cảnh báo bảo mật đều đặn. Ghim nó lại thì nó mục; bám theo nó thì nó biến động. Dù thế nào nó cũng là toàn bộ nền web của một renderer nằm trong chuỗi cung ứng của bạn chỉ để phục vụ một tài liệu. Một engine PHP in-process là một thư viện mã tập trung mà bạn có thể đọc; bề mặt bảo mật của nó là PHP bạn vốn đã chạy, không phải một nền tảng thứ hai mà giờ bạn cũng phải chạy.
Dữ liệu ở lại bên trong ranh giới tiến trình của bạn. Khi bạn gọi ra ngoài, nội dung tài liệu — vốn thường chính xác là dữ liệu nhạy cảm mà một PDF tồn tại để mang theo — vượt qua một ranh giới. Nó được ghi vào một pipe, một đối số, một tệp tạm, hay một network socket tới một service. Mỗi chỗ đó là một nơi để rò rỉ, để ghi log do sơ ý, hay để bỏ sót lại. In-process, dữ liệu không bao giờ rời worker sở hữu nó. Bán kính tác động là một tiến trình, không phải một đội máy.
Đường ống mong manh, khởi động nguội, và timeout. Các cú gọi liên-tiến-trình và qua mạng thất bại theo những cách mà một cú gọi hàm không thể: subprocess không khởi động, socket bị treo, timeout bạn đoán sai, khởi động nguội dưới một đợt lưu lượng tăng đột biến. Mỗi thứ cần một chính sách retry, một circuit breaker, và một ngân sách. Một lần kết xuất in-process hoặc trả về các byte hoặc ném ra một exception có kiểu mà bạn bắt ở dòng kế tiếp. Không có trạng thái mạng dang dở nào để dung hòa.
Quan sát và kiểm thử trở nên khó hơn qua ranh giới. Một thất bại trong một sidecar đến dưới dạng một mã thoát, một dòng log bị cắt cụt, hay một 500 từ một service bạn không kiểm soát. Tái hiện nó nghĩa là tái hiện cả môi trường đó. Một engine in-process quan sát được bằng các công cụ bạn vốn đã dùng — một stack trace, một debugger, một profiler — và nó kiểm thử được theo cách phần PHP còn lại của bạn được kiểm thử. Khả năng kiểm thử đó là một đặc tính chất lượng phần mềm có tên gọi: ISO/IEC 25010 xếp nó dưới khả năng bảo trì (Spec: ISO/IEC 25010:2023, §3.7ISO/IEC 25010:2023 §3.7), và một thư viện in-process thỏa mãn nó trực tiếp hơn nhiều so với một renderer mà bạn chỉ có thể vận hành bằng cách khởi chạy nó.
PDF mà những kiểm thử đó dựa vào là một cấu trúc đã được định nghĩa, không phải một hộp đen. Một tệp PDF có một bố cục đối tượng và tệp đã được đặc tả (Spec: ISO 32000-2, §7ISO 32000-2 §7), và một engine in-process phát ra cấu trúc đó từ mã bạn có thể đọc — nên một kiểm thử golden-file hay cấu trúc kiểm tra các byte do một hàm đã biết tạo ra, chứ không phải đầu ra của một chương trình bên ngoài mà bạn chỉ có thể quan sát.
Ví dụ thực tế
Phần tiêu đề “Ví dụ thực tế”Toàn bộ ý nằm gọn trong một nhúm dòng. Không có client, không có base URL, không có health check, và không có chính sách retry — bởi không có hệ thống thứ hai.
<?php
declare(strict_types=1);
require_once __DIR__ . '/vendor/autoload.php';
use NextPDF\Core\Document;
// The engine runs inside this very process. No subprocess is spawned,// no socket is opened, and the report data never leaves the worker.$document = Document::createStandalone();$document->setTitle('Quarterly Report');$document->addPage();
$html = <<<'HTML'<h1 style="color: #1E3A8A;">Quarterly Report</h1><p>Rendered <strong>in-process</strong> by PHP — no browser, no sidecar.</p>HTML;
$document->writeHtml($html);
// PDF bytes are returned directly. There is no boundary to marshal across,// so there is no timeout, cold start, or deserialization step to handle.$bytes = $document->getPdfData();Hãy đối chiếu với hình dạng của phiên bản sidecar — không phải mã của nó, mà hình dạng vận hành của nó. Nó cần một binary hay service được cài đặt và đến được tới, một request được tuần tự hóa và gửi đi, một timeout được chọn, một đường lỗi cho khi renderer nguội hoặc gục, và kết quả được marshal trở lại. Không cái nào trong số đó nằm trong đoạn mã trên, bởi không cái nào tồn tại khi engine là một thư viện.
Hiểu lầm thường gặp
Phần tiêu đề “Hiểu lầm thường gặp”Giả định thường gặp là kết xuất PDF “thật” buộc phải nghĩa là một trình duyệt, nên in-process hẳn là phiên bản đồ chơi. Điều đó hiểu ngược sự đánh đổi. Một trình duyệt là công cụ đúng khi bạn cần kết xuất chính xác, trung thực đến từng điểm ảnh nội dung web hiện đại tùy ý. Nó là mặc định sai cho công việc dạng tài liệu mà hầu hết các nhóm thực sự làm — hóa đơn, báo cáo, bảng sao kê, hợp đồng — nơi bố cục đã biết, dữ liệu là của bạn, và tính đúng đắn được kiểm tra bởi một bộ kiểm định, chứ không phải bằng mắt. Với công việc đó, sức nặng vận hành của một sidecar chẳng mua cho bạn thứ gì mà engine in-process không sẵn có, và lại làm bạn tốn mọi thứ trong các phần ở trên.
Hiểu lầm phản chiếu là cái mà trang này cẩn thận không phạm phải: khẳng định một engine in-process kết xuất “toàn bộ web” như một trình duyệt. Nó không, và NextPDF không giả vờ là nó làm được. Pipeline HTML in-process của nó là một tập con phù hợp đặc tả tập trung vào bố cục tài liệu, với các ranh giới đã được ghi tài liệu — phạm vi trung thực được trình bày trong the HTML pipeline. Khi bạn thực sự cần độ trung thực đầy đủ của một trình duyệt, đó là một sự ủy thác có chủ đích, được chọn bật, không phải một dự phòng âm thầm.
Giới hạn và ranh giới
Phần tiêu đề “Giới hạn và ranh giới”In-process là mặc định đúng. Nó không phải một khẳng định phổ quát rằng một subprocess không bao giờ chính đáng. Ở nơi một tài liệu thực sự đòi hỏi kết xuất chính xác CSS hiện đại tùy ý mà engine in-process không bao phủ, ủy thác cho một trình duyệt headless là lựa chọn đúng — và NextPDF hỗ trợ đường đó một cách có chủ đích, với truy cập mạng của nó bị giới hạn, như một đường nối chứ không phải mặc định. Hai cái không phải đối thủ; chúng là những công cụ khác nhau cho những công việc khác nhau.
Trang này lập luận về kiến trúc, không phải một ma trận hỗ trợ CSS. Chính xác HTML và CSS nào mà pipeline in-process bao phủ được định nghĩa bởi mã của engine và các kiểm thử tuân thủ của nó, và được ghi tài liệu cùng pipeline đó — không hứa hẹn ở đây. “In-process” mô tả đường kết xuất mặc định; nó không phải một khẳng định rằng mọi đường khả dĩ đều tránh một subprocess.
Bề mặt năng lực giữ được sự đơn giản: engine in-process là Core, và đường ủy-thác-trình-duyệt là một phần mở rộng tùy chọn, độc lập với phiên bản.
| Edition | Availability |
|---|---|
| Core | Core renders PDF in-process in PHP — no subprocess, binary, or sidecar by default. |
| Pro | The headless-browser delegation path is an optional add-on extension, independent of edition tier. |
| Enterprise | The headless-browser delegation path is an optional add-on extension, independent of edition tier. |
Tài liệu liên quan
Phần tiêu đề “Tài liệu liên quan”- The HTML pipeline — phạm vi trung thực của engine in-process, và chính xác khi nào ủy thác cho một trình duyệt là đúng.
- One engine, every framework — trục bổ trợ: cách cùng một engine in-process vươn tới mọi framework PHP mà không cần một thư viện khác cho mỗi stack.
- Operating NextPDF in production — việc vận hành một engine in-process trông ra sao mỗi ngày, với không một runtime phụ nào để vận hành.
- Memory and streaming — cách engine giữ cho việc tạo in-process bị giới hạn dưới tải.
Thuật ngữ
Phần tiêu đề “Thuật ngữ”- Tạo in-process — tạo PDF bên trong cùng một PHP worker xử lý request, mà không có subprocess, socket, hay service bên ngoài.
- Sidecar — một runtime riêng chạy song song với ứng dụng của bạn để làm một việc; ở đây, một binary bên ngoài, trình duyệt headless, hay microservice kết xuất PDF bên ngoài tiến trình của bạn.
- Khởi động nguội (cold start) — độ trễ và đợt tăng tài nguyên phát sinh khi một subprocess hay service phải được khởi động từ con số không trước khi nó có thể phục vụ request đầu tiên.
- IPC — giao tiếp liên-tiến-trình: các pipe, socket, tệp tạm, hay cú gọi mạng được dùng để truyền dữ liệu tới và đi từ một tiến trình riêng, và là một nguồn thất bại mong manh, khó gỡ lỗi tái diễn.
- Đường nối ủy-thác-trình-duyệt — đường tùy chọn, được chọn bật giao một lần kết xuất cho một trình duyệt headless để có độ trung thực chính xác, với truy cập mạng tới subresource bị chặn; một lựa chọn có chủ đích, không phải mặc định.