เหตุใดเอนจิน PDF ของคุณจึงควรอยู่ใน PHP ไม่ใช่ sidecar
Spec: ISO/IEC 25010:2023, §3.7ISO/IEC 25010:2023 §3.7Spec: ISO 32000-2, §7ISO 32000-2 §7
ภาพรวมโดยย่อ
หัวข้อที่มีชื่อว่า “ภาพรวมโดยย่อ”มีสองที่ที่ PDF ถูกสร้างได้: ภายในโพรเซส PHP ของคุณ หรือที่อื่นที่คุณต้องดำเนินการเอง NextPDF สร้างมันภายใน หน้านี้คือข้อโต้แย้งสำหรับทางเลือกนั้น — เหตุใดเอนจินแบบ in-process จึงมักเป็นค่าเริ่มต้นที่ถูกต้อง และรูปแบบ “ที่อื่น” นั้นมีต้นทุนเท่าไรจริงๆเมื่ออยู่ใน production
นี่คือมุมสถาปัตยกรรม ไม่ใช่มุมเฟรมเวิร์ก ส่วนเรื่องที่ว่าเอนจินตัวเดียวกันเข้าถึง Laravel, Symfony, CodeIgniter และโค้ดแบบสแตนด์อะโลนได้อย่างไรนั้นเป็นอีกเรื่องหนึ่ง เล่าไว้ใน เอนจินเดียว ทุกเฟรมเวิร์ก
เหตุใดเรื่องนี้จึงสำคัญ
หัวข้อที่มีชื่อว่า “เหตุใดเรื่องนี้จึงสำคัญ”ฟีเจอร์ PDF แทบไม่เคยเริ่มต้นเป็นระบบที่คุณต้องดำเนินการ มันเริ่มเป็นบรรทัดหนึ่งใน controller: เรนเดอร์ใบแจ้งหนี้นี้ ส่งรายงานนั้นกลับไป รูปแบบ sidecar เปลี่ยนบรรทัดนั้นให้เป็นโครงสร้างพื้นฐาน หากต้องการวาดเอกสาร ตอนนี้คุณต้องรันสิ่งที่สอง— ไบนารีภายนอก headless browser ไมโครเซอร์วิสที่แยกต่างหาก — และทุกอย่างที่สิ่งที่สองนั้นต้องการก็กลายเป็นปัญหาของคุณด้วย: เวอร์ชันของมัน หน่วยความจำของมัน คอนเทนเนอร์ของมัน เครือข่ายของมัน โหมดความล้มเหลวของมัน เพจเรียกเข้าเวรของมันตอนตีสอง
ต้นทุนมองไม่เห็นบนเดโม และเลี่ยงไม่ได้ใน production เอนจินเอกสารที่อยู่ในโพรเซสของคุณไม่มีต้นทุนเหล่านั้นเลยสักอย่าง คำถามไม่ใช่ “sidecar สร้าง PDF ได้หรือไม่” — แน่นอนว่าได้ แต่คือ “คุณรับปากจะดำเนินการอะไรเพื่อไปถึงตรงนั้น และคุณจำเป็นต้องทำไหม”
ฉบับย่อ
หัวข้อที่มีชื่อว่า “ฉบับย่อ”- In-process หมายถึงไม่มีรันไทม์ที่สอง NextPDF วาด PDF ภายใน เวิร์กเกอร์ PHP ตัวเดียวกับที่จัดการคำขอนั้น ไม่มี subprocess ให้ spawn ไม่มีเซอร์วิสให้ deploy และไม่มีอะไรพิเศษให้คอยเลี้ยงให้มีชีวิตอยู่
- sidecar เพิ่มพื้นผิวการดำเนินงานที่คุณไม่เคยมี browser ที่ bundle มา หรือไบนารีภายนอกพกเวอร์ชันของมันเอง รอยเท้าความปลอดภัยของมันเอง และ คอนเทนเนอร์ของมันเองมาด้วย — ซึ่งทั้งหมดนี้ตอนนี้คุณต้องแพตช์และเฝ้าดู
- ขอบเขตของโพรเซสคือจุดที่สิ่งต่างๆพังลง cold start, timeout, การต่อท่อ ระหว่างโพรเซสที่เปราะ และข้อมูลที่ออกไปจากโพรเซสของคุณ คือโหมดความล้มเหลว ที่การเรียกแบบ in-process ไม่มีเลย
- In-process ทดสอบได้และเป็นแบบกำหนดผลล่วงหน้าได้ เอนจินคือ PHP แบบมีชนิด ที่คุณ unit-test, mock และให้เหตุผลกับมันได้ — ไม่ใช่ renderer ทึบที่คุณ สำรวจได้เพียงด้วยการรันมันแล้วดูผลลัพธ์
- browser จริงก็ยังมีประโยชน์จริง สำหรับการเรนเดอร์หน้าเว็บสมัยใหม่ใดๆ อย่างซื่อตรงทุกพิกเซล headless browser คือเครื่องมือที่ซื่อตรง — และ NextPDF มอบหมายงานให้มันได้โดยจงใจ มันคือรอยต่อ ไม่ใช่ค่าเริ่มต้น
วิธีที่ NextPDF จัดการกับเรื่องนี้
หัวข้อที่มีชื่อว่า “วิธีที่ NextPDF จัดการกับเรื่องนี้”วางสถาปัตยกรรมสองแบบไว้ข้างกัน เส้นทาง in-process คือการเรียกฟังก์ชัน เส้นทาง sidecar คือระบบกระจายขนาดจิ๋ว — และทุกลูกศรระหว่างกล่องของมันคือจุดที่ล้มเหลวเป็นอิสระจากโค้ดของคุณ
- 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.
ไม่มีรันไทม์ที่สองให้ดำเนินการ รูปแบบ sidecar คือสองระบบที่สวมเครื่องแต่งกายของฟีเจอร์เดียว wkhtmltopdf ที่ bundle มา เซอร์วิส headless Chromium ไมโครเซอร์วิสเรนเดอร์ที่แยกต่างหาก — แต่ละตัวคือรันไทม์ที่มีจังหวะการปล่อยของมันเองและบั๊กของมันเอง คุณรับสืบทอดมันมาทั้งหมด เอนจินแบบ in-process ส่งมาในรูป Composer dependency มันถูกอัปเกรดในแบบเดียวกับไลบรารีตัวอื่นๆทุกตัวใน composer.json ของคุณ โดยไม่มี daemon, image หรือ socket เพิ่มเข้ามาใน deployment ของคุณ
Version drift และพื้นผิวความปลอดภัยที่กว้างขึ้น browser ที่ bundle มาคือ codebase ขนาดใหญ่ที่เคลื่อนที่เร็วพร้อมกระแสคำเตือนด้านความปลอดภัยที่ไม่ขาดสาย ปักหมุดมันไว้แล้วมันก็ผุ ตามมันไปแล้วมันก็ปั่นป่วน ไม่ว่าทางใดมันก็คือ web platform ทั้งแพลตฟอร์มของ renderer ที่นั่งอยู่ใน supply chain ของคุณเพื่อป้อนเอกสารเดียว เอนจิน PHP แบบ in-process คือไลบรารีของโค้ดที่โฟกัสซึ่งคุณอ่านได้ พื้นผิวความปลอดภัยของมันคือ PHP ที่คุณรันอยู่แล้ว ไม่ใช่แพลตฟอร์มที่สองที่ตอนนี้คุณต้องรันด้วย
ข้อมูลอยู่ภายในขอบเขตโพรเซสของคุณ เมื่อคุณ shell out เนื้อหาเอกสาร — ซึ่งมักเป็นข้อมูลอ่อนไหวพอดีที่ PDF มีไว้เพื่อพกพา — ข้ามขอบเขต มันถูกเขียนลง pipe, argument, temp file หรือ network socket ไปยังเซอร์วิส ทุกอันคือจุดที่จะรั่ว ถูกบันทึกไว้โดยบังเอิญ หรือถูกทิ้งค้างไว้ แบบ in-process ข้อมูลไม่เคยออกไปจากเวิร์กเกอร์ที่เป็นเจ้าของมัน รัศมีการระเบิดคือหนึ่งโพรเซส ไม่ใช่ทั้งกองเรือ
การต่อท่อที่เปราะ cold start และ timeout การเรียกระหว่างโพรเซสและผ่านเครือข่ายล้มเหลวในแบบที่การเรียกฟังก์ชันทำไม่ได้: subprocess ที่ไม่เริ่ม socket ที่ค้าง timeout ที่คุณเดาผิด cold start ภายใต้คลื่นทราฟฟิกที่พุ่งสูง แต่ละอย่างต้องการนโยบาย retry, circuit breaker และงบประมาณ การเรนเดอร์แบบ in-process ไม่ก็ส่งคืนไบต์ หรือไม่ก็โยน typed exception ที่คุณ catch ในบรรทัดถัดไป ไม่มีสถานะเครือข่ายบางส่วนให้ต้องปรับให้ตรงกัน
Observability และการทดสอบยากขึ้นเมื่อข้ามขอบเขต ความล้มเหลวใน sidecar มาถึงในรูป exit code, บรรทัด log ที่ถูกตัดทอน หรือ 500 จากเซอร์วิสที่คุณไม่ได้ควบคุม การทำให้มันเกิดซ้ำหมายถึงการทำให้สภาพแวดล้อมนั้นทั้งหมดเกิดซ้ำ เอนจินแบบ in-process สังเกตได้ด้วยเครื่องมือที่คุณใช้อยู่แล้ว — stack trace, debugger, profiler — และทดสอบได้ในแบบเดียวกับ PHP ส่วนที่เหลือของคุณ ความสามารถในการทดสอบนั้นคือคุณสมบัติด้านคุณภาพซอฟต์แวร์ที่มีชื่อ: ISO/IEC 25010 วางมันไว้ภายใต้ maintainability (Spec: ISO/IEC 25010:2023, §3.7ISO/IEC 25010:2023 §3.7) และไลบรารีแบบ in-process ก็ทำให้มันสำเร็จได้ตรงกว่า renderer ที่คุณออกแรงกับมันได้เพียงด้วยการเปิดใช้มันเท่านั้น
PDF ที่การทดสอบเหล่านั้นยืนยันคือโครงสร้างที่นิยามไว้ ไม่ใช่กล่องดำ ไฟล์ PDF มีเลย์เอาต์ของออบเจกต์และไฟล์ที่ระบุไว้ (Spec: ISO 32000-2, §7ISO 32000-2 §7) และเอนจินแบบ in-process สร้างโครงสร้างนั้นจากโค้ดที่คุณอ่านได้ — ดังนั้นการทดสอบแบบ golden-file หรือเชิงโครงสร้างจึงตรวจไบต์ที่ฟังก์ชันที่รู้จักสร้างขึ้น แทนที่จะเป็นผลลัพธ์ของโปรแกรมภายนอกที่คุณสังเกตได้เท่านั้น
ตัวอย่างเชิงปฏิบัติ
หัวข้อที่มีชื่อว่า “ตัวอย่างเชิงปฏิบัติ”ประเด็นทั้งหมดอยู่ในไม่กี่บรรทัด ไม่มี client ไม่มี base URL ไม่มี health check และไม่มีนโยบาย retry — เพราะไม่มีระบบที่สอง
<?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();ลองเทียบรูปทรงของเวอร์ชัน sidecar — ไม่ใช่โค้ดของมัน แต่รูปทรง เชิงการดำเนินงาน ของมัน มันต้องการไบนารีหรือเซอร์วิสที่ติดตั้งและเข้าถึงได้ คำขอที่ serialize แล้วส่ง timeout ที่เลือกไว้ เส้นทางความล้มเหลวสำหรับเมื่อ renderer เย็นหรือล่ม และผลลัพธ์ที่ marshal กลับมา ไม่มีสิ่งใดในนั้นอยู่ใน snippet ข้างบน เพราะไม่มีสิ่งใดในนั้นมีอยู่เมื่อเอนจินคือไลบรารี
ความเข้าใจผิดที่พบบ่อย
หัวข้อที่มีชื่อว่า “ความเข้าใจผิดที่พบบ่อย”ข้อสันนิษฐานที่พบบ่อยคือการเรนเดอร์ PDF “ของจริง” ต้องหมายถึง browser ดังนั้น in-process จึงต้องเป็นเวอร์ชันของเล่น นั่นเข้าใจการแลกได้แลกเสียกลับด้าน browser คือเครื่องมือที่ถูกต้องเมื่อคุณต้องการการเรนเดอร์เนื้อหาเว็บสมัยใหม่ ใดๆ อย่างเป๊ะและซื่อตรงทุกพิกเซล มันคือค่าเริ่มต้นที่ผิดสำหรับงานรูปทรงเอกสารที่ทีมส่วนใหญ่ทำกันจริง — ใบแจ้งหนี้ รายงาน ใบแจ้งยอด สัญญา — ที่เลย์เอาต์เป็นที่รู้กัน ข้อมูลเป็นของคุณ และความถูกต้องตรวจโดยตัวตรวจสอบความถูกต้อง ไม่ใช่ด้วยตา สำหรับงานนั้น น้ำหนักเชิงการดำเนินงานของ sidecar ไม่ได้ซื้ออะไรให้คุณที่เอนจินแบบ in-process ไม่ได้ให้อยู่แล้ว และทำให้คุณเสียทุกอย่างในหัวข้อด้านบน
ความเข้าใจผิดในกระจกเงาคือสิ่งที่หน้านี้ระวังที่จะไม่ทำ: การอ้างว่าเอนจินแบบ in-process เรนเดอร์ “ทั้งเว็บ” ได้เหมือน browser มันทำไม่ได้ และ NextPDF ก็ไม่แสร้งว่าทำได้ ไปป์ไลน์ HTML แบบ in-process ของมันคือชุดย่อยที่สอดคล้องกับข้อกำหนดซึ่งโฟกัสที่การจัดวางเอกสาร พร้อมขอบเขตที่มีเอกสารกำกับ — ขอบเขตที่ซื่อตรงวางไว้ใน ไปป์ไลน์ HTML เมื่อคุณต้องการความซื่อตรงระดับ browser เต็มรูปแบบจริงๆ นั่นคือการมอบหมายแบบเลือกใช้โดยจงใจ ไม่ใช่การสำรองทางแบบเงียบๆ
ขีดจำกัดและขอบเขต
หัวข้อที่มีชื่อว่า “ขีดจำกัดและขอบเขต”In-process คือค่าเริ่มต้นที่ถูกต้อง มันไม่ใช่การอ้างแบบครอบจักรวาลว่า subprocess ไม่มีวันมีเหตุผลรองรับ ในที่ที่เอกสารต้องการการเรนเดอร์ CSS สมัยใหม่ใดๆอย่างเป๊ะซึ่งเอนจินแบบ in-process ไม่ครอบคลุมจริงๆ การมอบหมายให้ headless browser คือทางเลือกที่ถูกต้อง — และ NextPDF รองรับเส้นทางนั้นโดยจงใจ โดยจำกัดการเข้าถึงเครือข่ายของมัน ในฐานะรอยต่อ ไม่ใช่ค่าเริ่มต้น ทั้งสองไม่ใช่คู่แข่ง แต่เป็นเครื่องมือคนละอย่างสำหรับงานคนละอย่าง
หน้านี้โต้แย้งเรื่องสถาปัตยกรรม ไม่ใช่ตารางการรองรับ CSS ส่วนที่ว่าไปป์ไลน์ in-process ครอบคลุม HTML และ CSS ตัวใดบ้างนั้น ถูกนิยามโดยโค้ดของเอนจินและการทดสอบความสอดคล้องของมัน และมีเอกสารกำกับไว้พร้อมกับไปป์ไลน์นั้น — ไม่ได้สัญญาไว้ที่นี่ “In-process” อธิบายเส้นทางการเรนเดอร์ค่าเริ่มต้น มันไม่ใช่การอ้างว่าทุกเส้นทางที่เป็นไปได้เลี่ยง subprocess
พื้นผิวความสามารถยังคงเรียบง่าย: เอนจินแบบ in-process คือ Core และเส้นทางการมอบหมายให้ browser เป็นส่วนขยายแบบเลือกได้ ที่เป็นอิสระจากรุ่น
| 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. |
เอกสารที่เกี่ยวข้อง
หัวข้อที่มีชื่อว่า “เอกสารที่เกี่ยวข้อง”- ไปป์ไลน์ HTML — ขอบเขตที่ซื่อตรงของ เอนจินแบบ in-process และเวลาที่การมอบหมายให้ browser ถูกต้องพอดี
- เอนจินเดียว ทุกเฟรมเวิร์ก — แกนที่เสริมกัน: วิธีที่เอนจินแบบ in-process ตัวเดียวกันเข้าถึงทุกเฟรมเวิร์ก PHP โดยไม่ต้องมีไลบรารีต่างกันต่อหนึ่งสแตก
- การดำเนินงาน NextPDF ใน production — การรันเอนจินแบบ in-process มีหน้าตาอย่างไรในแต่ละวัน โดยไม่มีรันไทม์ เพิ่มเติมให้ดำเนินการ
- หน่วยความจำและการสตรีม — วิธีที่ เอนจินรักษาการสร้างแบบ in-process ให้มีขอบเขตจำกัดภายใต้ภาระงาน
อภิธานศัพท์
หัวข้อที่มีชื่อว่า “อภิธานศัพท์”- In-process generation — การสร้าง PDF ภายในเวิร์กเกอร์ PHP ตัวเดียวกัน ที่จัดการคำขอ โดยไม่มี subprocess, socket หรือเซอร์วิสภายนอก
- Sidecar — รันไทม์ที่แยกต่างหากซึ่งรันควบคู่ไปกับแอปพลิเคชันของคุณเพื่อทำ งานเดียว ในที่นี้คือไบนารีภายนอก headless browser หรือไมโครเซอร์วิสที่เรนเดอร์ PDF นอกโพรเซสของคุณ
- Cold start — ความหน่วงและการพุ่งของทรัพยากรที่เกิดขึ้นเมื่อ subprocess หรือเซอร์วิสต้องถูกเริ่มจากศูนย์ก่อนที่มันจะให้บริการคำขอแรกได้
- IPC — inter-process communication คือ pipe, socket, temp file หรือ การเรียกผ่านเครือข่ายที่ใช้ส่งข้อมูลไปและกลับจากโพรเซสที่แยกต่างหาก และเป็น แหล่งความล้มเหลวที่เปราะและดีบักยากซ้ำๆ
- Browser-delegation seam — เส้นทางแบบเลือกใช้โดยจงใจที่ส่งการเรนเดอร์ให้ headless browser เพื่อความซื่อตรงที่เป๊ะ โดยบล็อกการเข้าถึงเครือข่ายของ subresource เป็นทางเลือกโดยจงใจ ไม่ใช่ค่าเริ่มต้น