Artisan trong production
Tổng quan nhanh
Phần tiêu đề “Tổng quan nhanh”Trong môi trường production, hãy inject một renderer đã được cấu hình cùng một logger PHP Standards Recommendation 3 (PSR-3), tái sử dụng tiến trình Chrome đang chạy giữa các lần kết xuất, đặt chiều cao tường minh cho tài liệu có nhiều phần tử và giới hạn đường kết xuất bằng một timeout ở lớp trên.
Tổng quan khái niệm
Phần tiêu đề “Tổng quan khái niệm”BrowserPool duy trì một tiến trình Chrome luôn chạy (keepAlive: true) và khởi động lại tiến trình đó sau mỗi 100 lần kết xuất để hạn chế mức tăng bộ nhớ, một dạng tích lũy đã biết ở các client Chrome DevTools Protocol (CDP) chạy lâu dài. Với một worker kết xuất nhiều tài liệu, hãy dùng một renderer sống lâu thay vì tạo một renderer cho từng yêu cầu, để hiếm khi phải trả chi phí khởi động Chrome.
Mã ví dụ — Production
Phần tiêu đề “Mã ví dụ — Production”<?php
declare(strict_types=1);
use NextPDF\Artisan\ChromeHtmlRenderer;use NextPDF\Artisan\ChromeRendererConfig;use NextPDF\Artisan\Exception\ChromeNotAvailableException;use NextPDF\Artisan\Exception\ChromeRenderException;use Psr\Log\LoggerInterface;
final class ReportRenderer{ private ChromeHtmlRenderer $renderer;
public function __construct(LoggerInterface $logger) { $config = ChromeRendererConfig::fromArray([ 'chrome_binary' => getenv('CHROME_BINARY') ?: null, 'render_timeout' => 45, 'max_html_size' => 2_000_000, 'no_sandbox' => (bool) getenv('CHROME_NO_SANDBOX'), ]);
$this->renderer = new ChromeHtmlRenderer($config, $logger); }
public function render(string $html, float $widthPt, float $heightPt = 0.0): string { try { return $this->renderer->render($html, $widthPt, $heightPt)->getPdfData(); } catch (ChromeNotAvailableException $e) { // Deployment fault: Chrome runtime missing. Page the on-call owner. throw $e; } catch (ChromeRenderException $e) { // Render-time fault: timeout, crash, empty output. Retryable once. throw $e; } }
public function shutdown(): void { $this->renderer->close(); }}Hãy khởi tạo renderer một lần, rồi tái sử dụng nó. Gọi close() khi worker tắt để giải phóng tiến trình Chrome một cách xác định thay vì chờ destructor. Hai nhánh catch tách lỗi triển khai (thiếu runtime) khỏi lỗi trong lúc kết xuất (có thể thử lại). Đừng dùng khối catch rỗng.
Hãy gắn nó vào container dưới dạng singleton:
$container->singleton(ReportRenderer::class, fn ($c) => new ReportRenderer($c->get(Psr\Log\LoggerInterface::class)));Xử lý chiều cao
Phần tiêu đề “Xử lý chiều cao”Khi bạn bỏ qua chiều cao, cầu nối sẽ đo chiều cao nội dung trong Chrome (max của các chiều cao scroll và offset của body/document), chuyển sang điểm và cộng thêm một vùng đệm an toàn khoảng 0,2 inch (khoảng 14,4 pt). Vùng đệm này bù cho độ lệch giữa bố cục viewport của Chrome và quá trình reflow bố cục in. Nếu không có nó, printToPDF có thể đẩy nội dung tràn sang trang thứ hai, rồi bị PageImporter (chỉ trang 0) cắt bỏ. Cầu nối áp đặt chiều cao giấy tối thiểu là 0,1 inch. Các test ChromeHtmlRendererTest::renderUsesAutoFitHeightByDefault, ::renderAutoFitBufferIsAddedNotSubtracted và ::renderAppliesMinimumHeightOf0Point1InchForTinyExplicitHeight kiểm chứng hành vi này.
Với tài liệu có bố cục cố định (hóa đơn, chứng chỉ), hãy truyền chiều cao tường minh theo điểm. Khi chiều cao đã tường minh, không có vùng đệm nào được thêm vào, và đầu ra khớp chính xác với khổ giấy được yêu cầu (được kiểm chứng bởi ::renderHonorsExplicitHeightWithoutAutoBuffer).
Batch worker
Phần tiêu đề “Batch worker”- Hãy khởi tạo một renderer cho mỗi worker và tái sử dụng nó.
BrowserPooltái sử dụng trình duyệt đang chạy và tự động khởi động lại ở mốc 100 lần kết xuất. - Hãy gọi
close()khi worker tắt và giữa các batch lớn khi bạn muốn có một tiến trình Chrome mới sớm hơn mốc 100 lần kết xuất. - Destructor gọi
close(), nhưng lời gọiclose()tường minh có tính xác định hơn và được ưu tiên trong các tiến trình chạy lâu dài. - Thông báo khởi động lại được ghi log ở mức
noticekèm số lần kết xuất; hãy cảnh báo khi tỷ lệ khởi động lại tăng cao vì điều đó cho thấy tài liệu nặng hơn dự kiến.
Khả năng quan sát
Phần tiêu đề “Khả năng quan sát”Hãy inject một logger PSR-3. Renderer phát ra các sự kiện và mức log sau:
| Sự kiện | Mức | Ngữ cảnh |
|---|---|---|
| Bắt đầu kết xuất | debug | size, width, height |
| Kết xuất hoàn tất | debug | pdfSize, contentHeight |
| Khởi chạy trình duyệt | info | binary |
| Khởi động lại trình duyệt | notice | count |
| Đóng trình duyệt | debug | renderCount |
Không có HTML, byte PDF hay văn bản đã trích xuất nào được ghi log. Điều này giữ payload nằm ngoài log vận hành và phù hợp với hướng dẫn về nội dung log của National Institute of Standards and Technology Special Publication (NIST SP) 800-92. Hãy xây dựng các mục tiêu mức dịch vụ (SLO) về độ trễ từ cặp start/complete, và tạo cảnh báo về tỷ lệ khởi động lại dựa trên các sự kiện notice.
Các mẫu triển khai
Phần tiêu đề “Các mẫu triển khai”- Sidecar Chrome: chạy Chrome trong cùng container với PHP worker; ghim
chrome_binary. Hãy cấp phát một container hỗ trợ sandbox; xem /integrations/artisan/chrome-renderer-setup/. - Không container / CLI: Artisan không có container dependency injection. Hãy dùng
EInvoiceServiceFactorycho các hợp đồng e-invoice Premium trong các runner giao diện dòng lệnh (CLI); xem /integrations/artisan/boot-and-discovery/. - Giới hạn tài nguyên: hãy ghép
render_timeoutvới ngân sách yêu cầu ở lớp trên và cgroup/ulimit của host. Xem mô hình mối đe dọa tại /integrations/artisan/security-and-operations/.
Các trường hợp biên & điều cần lưu ý
Phần tiêu đề “Các trường hợp biên & điều cần lưu ý”- Một renderer gặp lỗi giữa lúc kết xuất vẫn đóng trang Chrome (
finally), và pool vẫn dùng được. - Không hỗ trợ tái sử dụng một renderer trên nhiều threads/processes; một renderer sở hữu một tiến trình Chrome.
- Mốc khởi động lại sau 100 lần kết xuất là cố định; hãy tính kích thước batch dựa trên mốc đó để các đợt tăng độ trễ vẫn dự đoán được.
Hiệu năng
Phần tiêu đề “Hiệu năng”Chi phí ở trạng thái ổn định đến từ phần bố cục đầu vào của Chrome cộng với printToPDF, chứ không phải overhead của cầu nối. keepAlive phân bổ chi phí khởi động trải đều qua các lần kết xuất. Hãy lường trước một đợt tăng độ trễ ở mỗi lần kết xuất thứ 100 (khởi động lại tiến trình); hãy đưa nó vào các SLO thay vì xem đó là sự cố.
Ghi chú bảo mật
Phần tiêu đề “Ghi chú bảo mật”Các đường dẫn production nhận HTML không tin cậy. Hãy đọc lại /integrations/artisan/security-and-operations/. Các rào cản mạng vẫn giữ nguyên bất kể cấu hình, nhưng no_sandbox: true loại bỏ sự cô lập tiến trình Chrome và nâng yêu cầu về độ tin cậy của đầu vào.
Bối cảnh thương mại
Phần tiêu đề “Bối cảnh thương mại”Trong các worker không container, EInvoiceServiceFactory trả về null khi Premium chưa được cài đặt, nên đường kết xuất nguồn mở tiếp tục không thay đổi. Hãy cài đặt Pro/Enterprise để bật tính năng nhúng và xác thực e-invoice trên tài liệu đã kết xuất.
Xem thêm
Phần tiêu đề “Xem thêm”- /integrations/artisan/quickstart/
- /integrations/artisan/configuration/
- /integrations/artisan/security-and-operations/
- /integrations/artisan/chrome-renderer-setup/
- /integrations/artisan/troubleshooting/