2. 压测场景库设计原则
构建一个高质量的 Outbox 表压测场景库,不能仅靠零散脚本的堆砌。必须遵循一套明确的设计原则,确保场景库能够真实反映生产负载、支撑长期性能演进,并降低维护成本。本章围绕构建目标、模块化设计、可复用性与可扩展性三大核心原则展开。
2.1 压测场景库的构建目标
场景库的终极目标是模拟真实、量化瓶颈、驱动优化。具体拆解为以下四个子目标:
| 目标维度 | 说明 | Outbox 场景示例 |
|---|---|---|
| 负载真实性 | 模拟生产环境的流量特征(并发、数据量、峰值) | 订单创建高峰时 Outbox 表每秒写入 5000 条记录 |
| 瓶颈可复现 | 稳定触发已知或潜在的性能瓶颈 | Outbox 表主键争用、死锁、Binlog 堆积 |
| 指标可量化 | 输出明确的性能指标(TPS、P99 延迟、资源消耗) | 数据传输优化前后 P99 延迟从 120ms 降至 45ms |
| 优化可验证 | 为每一次架构或代码变更提供 A/B 对比依据 | 批量写入 vs 单条写入的吞吐量对比 |
实践要点:每个场景必须绑定一个明确的“压测通过标准”。例如:“在 1000 并发下,Outbox 表写入 TPS ≥ 8000,且无死锁报错。” 没有通过标准的场景,无法驱动优化决策。
2.2 模块化设计
模块化是场景库可维护性的基石。将压测场景拆解为数据层、事务层、传输层、监控层四个独立模块,每个模块可单独替换或升级。
2.3 可复用性要求
场景库中的组件应具备一次编写、多处运行的能力。避免为每个测试目标重复造轮子。可复用性体现在以下三个层面:
- 数据模板复用:定义通用的 Outbox 记录结构(event_id, aggregate_type, payload, status, created_at),通过参数化注入不同的业务语义。
- 压测脚本复用:将“写入 Outbox”、“拉取未发送记录”、“标记已发送”封装为独立函数,通过 YAML/JSON 配置驱动不同场景。
- 监控面板复用:设计通用的 Grafana 看板模板,涵盖 Outbox 表写入 TPS、传输延迟、死锁次数、Binlog 积压量等核心指标。
代码示例:可复用的 Outbox 写入函数(Java + JMeter 插件)
// 可复用的 Outbox 写入器
public class OutboxWriter {
private final DataSource dataSource;
private final String insertSql;
public OutboxWriter(DataSource dataSource, String tableName) {
this.dataSource = dataSource;
this.insertSql = String.format(
"INSERT INTO %s (event_id, aggregate_type, payload, status, created_at) VALUES (?, ?, ?, 'PENDING', NOW())",
tableName
);
}
public void write(String eventId, String aggregateType, String payload) {
try (Connection conn = dataSource.getConnection();
PreparedStatement ps = conn.prepareStatement(insertSql)) {
ps.setString(1, eventId);
ps.setString(2, aggregateType);
ps.setString(3, payload);
ps.executeUpdate();
} catch (SQLException e) {
throw new RuntimeException("Outbox 写入失败", e);
}
}
}
2.4 可扩展性要求
压测场景库必须能够平滑适应业务增长和架构演进。可扩展性设计遵循以下原则:
| 扩展维度 | 设计要求 | Outbox 场景示例 |
|---|---|---|
| 数据规模扩展 | 支持从单表到分库分表的无缝切换 | Outbox 表从单表扩展到 16 个分片 |
| 传输协议扩展 | 支持新增传输通道(Kafka / RocketMQ / Pulsar) | 从 Kafka 切换到 RocketMQ,不改动压测主流程 |
| 并发模型扩展 | 支持从单线程到协程/线程池的灵活配置 | 压测配置中调整 concurrency=200,自动分配线程 |
| 监控集成扩展 | 支持对接不同监控系统(Prometheus / Datadog / SkyWalking) | 通过 SPI 机制加载不同的监控上报实现 |
常见陷阱:不要将压测场景与具体中间件版本强绑定。例如,不要在脚本中硬编码 Kafka 2.8 的 API 调用,而应使用通用客户端抽象层。否则,升级 Kafka 到 3.0 时,整个场景库可能面临重写。
2.5 设计原则总结
将上述原则归纳为一张决策检查表,供场景库设计时逐项核对: