Chaos:确定性韧性场景测试框架
Chaos 模块是用于韧性测试的小型框架。你可以注册实现单方法接口的故障注入场景、执行这些场景,并收集一份结构化 pass/fail 报告。它刻意保持极简——仅有五个类——用于韧性测试套件与混沌演练(chaos-day),而不是文档生成路径。
稳定性:实验性。 这是一个测试与韧性工具层, 并非核心 PDF API。其 SPI 规模小且形态稳定,但本模块的范围与随附场景仍在演进。请勿基于它构建生产环境控制流程。
composer require nextpdf/core:^3概念总览
标题为“概念总览”的章节韧性测试关注的是:当某个依赖项失效时,引擎是否能正确降级?Chaos 模块为这类测试提供结构。ChaosScenarioInterface 是场景需要实现的契约——包含一个 name(),以及一个返回 ChaosOutcome 的 simulate()。一个场景封装单个故障(网络分区、一系列检索后端的 5xx 响应),并报告发生的情况。
ChaosScenarioRunner 是协调者。你会用 register() 注册场景、调用 run() 按注册顺序依次执行它们,并读取汇总结果:outcomes()、allPassed()、passCount()、failCount()。此 runner 绝不会因场景失败而抛出异常——失败是捕获到 ChaosOutcome 中的数据,而不是异常。它只会在自身基础设施故障时抛出异常:无效的场景注册,或无法写入报告文件(ChaosReportWriteException)。无法访问受测资源的场景,会暴露一个 RetrievalUnavailableException。整个模块标记为 @since 3.2.0。
ChaosOutcome 是每个场景的结果:pass/fail、一段持续时间,以及供结构化报告使用的 toArray()。由于 outcome 会记录墙钟(wall-clock)持续时间,该报告的可复现性配置为 structural,而非 bitwise。
API 接口
标题为“API 接口”的章节| 类型 | 主要成员 | 角色 |
|---|---|---|
ChaosScenarioInterface | name(): string、simulate(): ChaosOutcome | 场景契约(@since 3.2.0) |
ChaosScenarioRunner | register()、run()、outcomes()、allPassed()、passCount()、failCount() | 顺序场景协调者(@since 3.2.0) |
ChaosOutcome | durationSeconds()、toArray() | 每个场景的 pass/fail 结果(@since 3.2.0) |
RetrievalUnavailableException | — | 无法访问某个受测资源 |
ChaosReportWriteException | — | 无法写入报告文件 |
执行 composer docs:generate-api-php -- --module=Chaos 获取完整的 PHPDoc 表格。
代码示例——快速上手
标题为“代码示例——快速上手”的章节注册一个场景并执行测试套件。
<?php
declare(strict_types=1);
require_once __DIR__ . '/../vendor/autoload.php';
use NextPDF\Chaos\ChaosOutcome;use NextPDF\Chaos\ChaosScenarioInterface;use NextPDF\Chaos\ChaosScenarioRunner;
final class TimeoutScenario implements ChaosScenarioInterface{ public function name(): string { return 'dependency-timeout'; }
public function simulate(): ChaosOutcome { // Inject the fault, observe the engine's degradation, return the verdict. return new ChaosOutcome(/* name, passed, durationSeconds, details */); }}
$runner = new ChaosScenarioRunner();$runner->register(new TimeoutScenario());$runner->run();
echo $runner->allPassed() ? "Resilient.\n" : "{$runner->failCount()} scenario(s) failed.\n";代码示例——生产环境
标题为“代码示例——生产环境”的章节在韧性作业(resilience job)中驱动此框架,将任何失败视为非零退出码,同时避免让场景失败以异常形式逸出。
<?php
declare(strict_types=1);
require_once __DIR__ . '/../vendor/autoload.php';
use NextPDF\Chaos\ChaosScenarioRunner;use NextPDF\Chaos\Exception\ChaosReportWriteException;use Psr\Log\LoggerInterface;
final readonly class ChaosJob{ /** @param list<\NextPDF\Chaos\ChaosScenarioInterface> $scenarios */ public function __construct( private array $scenarios, private LoggerInterface $logger, ) {}
public function run(string $reportPath): int { $runner = new ChaosScenarioRunner();
foreach ($this->scenarios as $scenario) { $runner->register($scenario); }
$runner->run(); // never throws on scenario failure
try { $runner->writeReport($reportPath); } catch (ChaosReportWriteException $e) { $this->logger->error('Chaos report could not be written.', ['error' => $e->getMessage()]);
return 2; }
return $runner->allPassed() ? 0 : 1; }}边界情况与注意事项
标题为“边界情况与注意事项”的章节run()绝不会因为某个场景失败而抛出异常。失败存在于ChaosOutcome之中。如果你把run()包在一个预期能在其中捕获失败的 try/catch 中,你永远不会看到那些失败——请改为读取failCount()/allPassed()。- 此 runner 只会在基础设施故障时抛出异常:注册错误,或报告路径不可写时的
ChaosReportWriteException。请将这些异常与场景结果分开处理。 - 场景会按注册顺序依次执行。没有并行处理。若多个场景共用外部状态,执行顺序可能会影响结果。
- 本模块用于韧性测试。请勿将此 runner 作为控制机制接入文档生成路径。
此 runner 的开销可以忽略不计。成本取决于场景实际执行的工作。由于场景会注入故障并可能等待超时,一次混沌执行按设计本来就可能很慢。此处的 performance_budget 是引擎参考值,并非场景持续时间的上限。其可复现性配置为 structural:报告会记录墙钟持续时间,因此两次执行在这些字段上会有所不同。
安全性注意事项
标题为“安全性注意事项”的章节场景会注入故障,并可能触发依赖项中的失败路径。只在测试或预发布(staging)环境中执行此框架,并确保其凭据与端点都限定在该环境内——绝不可针对生产环境系统执行。报告可能包含关于失败模式的诊断细节。请将其视为内部数据,并在分享前按本项目的日志清理(log-scrubbing)要求处理。请参阅 /modules/core/security/ 中的引擎威胁模型。
符合性
标题为“符合性”的章节本模块不提出任何关于 PDF 规范的规范性声明。它是韧性工具。它未实现任何需要引用条款的标准化协议。引擎符合性由 /modules/core/conformance/ 中所述的 oracle 与黄金套件(golden suites)验证。
另请参阅
标题为“另请参阅”的章节- Observability 模块 — 场景所观察的运行时状态面。
- Accelerator 模块 — 依赖项失效场景的常见目标。
- 符合性总览
- 引擎安全模型