Worker 模式指南
架構概觀
┌─────────────────────────────────────────────────┐
│ 程序級別(啟動時初始化一次) │
│ ┌─────────────────┐ ┌─────────────────────┐ │
│ │ FontRegistry │ │ ImageRegistry │ │
│ │ (字型索引) │ │ (圖像快取) │ │
│ └────────┬────────┘ └──────────┬──────────┘ │
│ └──────────┬───────────┘ │
│ ┌────▼────────┐ │
│ │DocumentFactory│ │
│ └────┬────────┘ │
└──────────────────────│──────────────────────────┘
│ 每個請求
┌─────────────┼─────────────┐
▼ ▼ ▼
Document Document Document
(可棄式) (可棄式) (可棄式)
基本設定
use NextPDF\Core\DocumentFactory;
use NextPDF\Core\Support\FontRegistry;
use NextPDF\Core\Support\ImageRegistry;
use NextPDF\Core\Accelerator\SpectrumClient;
// === 程序啟動時執行一次 ===
$fontRegistry = FontRegistry::create()
->registerDirectory('/fonts/system')
->registerFont(path: '/fonts/custom/NotoSansCJKtc.otf', alias: 'NotoSansCJKtc');
$imageRegistry = ImageRegistry::create()
->withCacheSize(maxEntries: 100);
$spectrum = SpectrumClient::create(); // 可選,Rust 加速
$factory = DocumentFactory::create(
fontRegistry: $fontRegistry,
imageRegistry: $imageRegistry,
accelerator: $spectrum, // 可選
);
// === 每個請求 ===
function handleRequest(DocumentFactory $factory): void
{
$document = $factory->make(pageSize: PageSize::A4);
// ... 渲染內容 ...
$document->save('/output/file.pdf');
// $document 超出作用域後自動釋放
}
Laravel 整合
Service Provider 設定
// app/Providers/NextPdfServiceProvider.php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
use NextPDF\Core\DocumentFactory;
use NextPDF\Core\Support\FontRegistry;
use NextPDF\Core\Support\ImageRegistry;
final class NextPdfServiceProvider extends ServiceProvider
{
public function register(): void
{
$this->app->singleton(FontRegistry::class, static function (): FontRegistry {
return FontRegistry::create()
->registerDirectory(config('nextpdf.fonts_path'));
});
$this->app->singleton(ImageRegistry::class, static function (): ImageRegistry {
return ImageRegistry::create();
});
$this->app->singleton(DocumentFactory::class, static function ($app): DocumentFactory {
return DocumentFactory::create(
fontRegistry: $app->make(FontRegistry::class),
imageRegistry: $app->make(ImageRegistry::class),
);
});
}
}
Laravel Octane 整合
// config/octane.php
return [
'warm' => [
\NextPDF\Core\DocumentFactory::class, // 在 Octane 啟動時預熱
],
'flush' => [
// DocumentFactory 不需要 flush,Registry 設計為執行緒安全
],
];
Symfony 整合
# config/services.yaml
services:
NextPDF\Core\Support\FontRegistry:
factory: ['NextPDF\Core\Support\FontRegistry', 'create']
calls:
- registerDirectory: ['%kernel.project_dir%/fonts']
shared: true
NextPDF\Core\DocumentFactory:
factory: ['NextPDF\Core\DocumentFactory', 'create']
arguments:
$fontRegistry: '@NextPDF\Core\Support\FontRegistry'
$imageRegistry: '@NextPDF\Core\Support\ImageRegistry'
shared: true
佇列工作(Queue Workers)
// Laravel Job
final class GeneratePdfJob implements ShouldQueue
{
public function __construct(
private readonly string $templateId,
private readonly array $data,
) {}
public function handle(DocumentFactory $factory): void
{
$document = $factory->make(pageSize: PageSize::A4);
// ... 渲染 ...
$document->save(storage_path("pdfs/{$this->templateId}.pdf"));
}
}
並發控制
Cloudflare Workers
use NextPDF\Cloudflare\CloudflareDocumentFactory;
// Cloudflare Workers 使用特殊工廠(無 FFI 依賴)
$factory = CloudflareDocumentFactory::create(
fontsBaseUrl: 'https://assets.example.com/fonts',
);
監控與可觀測性
延伸閱讀