42 lines
3.0 KiB
Markdown
42 lines
3.0 KiB
Markdown
# P6 真实慢消费者背压回归
|
||
|
||
日期:2026-09-20。本批在一次性 MySQL 和真实 Orbit HTTP/WebSocket 服务上验证 SDK 消费器容量为 1 时的慢处理器背压。它补充 SDK 连接层重连边界,不代表跨节点重连、全局积压容量、磁盘/锁等待或生产 RPO/RTO 验收。
|
||
|
||
## 场景和结果
|
||
|
||
`TestIntegrationEventConsumerSlowHandlerBackpressure` 先投递一条取消结果,启动正式 `EventConsumer`,让第一个处理器停在业务处理阶段;处理器容量固定为 1。随后再产生第二条结果,测试通过真实订阅读取确认两条交付均已持久化,但在释放第一个处理器之前没有启动第二次处理,也没有提交 ACK。释放后两条交付都完成并各自只尝试一次。
|
||
|
||
| 证据 | 结果 |
|
||
| --- | ---: |
|
||
| 消费器本地容量 | 1 |
|
||
| 持久化交付 | 2 |
|
||
| 处理器调用(释放前) | 1 |
|
||
| ACK(释放前) | 0 |
|
||
| 处理器调用(最终) | 2 |
|
||
| ACK(最终) | 2 |
|
||
| 每条交付 attempts | 1、1 |
|
||
| 重复处理 | 0 |
|
||
|
||
`TestIntegrationEventProcessSlowConsumerPeerProgress` 另外启动两个真实 Orbit 进程和两个独立 WebSocket 消费器:节点 A 持有第一条交付并阻塞,节点 B 在同一订阅上领取并确认第二条交付;释放 A 后第一条再确认。两个节点身份不同,最终两条交付仍各一次尝试。
|
||
|
||
同批定向真实服务回归还运行了 ACK 提交回执丢失和自然租约补发:三项合计 52.645 秒,均通过;单节点慢消费者用例本身 3.15 秒。双进程用例另以两个真实 Orbit 进程运行 3.125 秒并通过。环境为 Docker Go 1.25.14 Linux arm64、一次性 MySQL 8.4.10,服务端和 SDK 使用临时 modfile,仓库声明的 Go 1.27.1 未修改。`go test -race` 通过,数据库外键为 0。
|
||
|
||
## 结论边界
|
||
|
||
该用例证明容量窗口会把慢处理器期间的后续结果留在服务端,释放后按原交付身份继续消费,不会在 SDK 内存中并行启动超出容量的处理器。业务处理器仍必须响应 context 取消,并在业务 Inbox 去重与业务效果同一事务提交后才返回成功。
|
||
|
||
当前仍未验证连接风暴叠加积压、租约到期期间的业务 Inbox 去重、数据库锁/连接池/磁盘曲线和目标拓扑生产容量;本次双进程只证明一个慢消费者不会阻塞同一订阅的对等节点,不证明跨故障域切换、全局公平或容量上限。上述项目必须在目标拓扑中另行执行,不能由本次样本推导。
|
||
|
||
## 复现
|
||
|
||
在一次性 MySQL、迁移完成、带 `worker-access` 与 `event-access` 的凭据以及真实 Orbit 服务后,执行:
|
||
|
||
```sh
|
||
cd sdk/go
|
||
ORBIT_TEST_WORKER_URL=http://127.0.0.1:$PORT \
|
||
ORBIT_TEST_WORKER_CREDENTIALS_FILE=/tmp/orbit-event-test/credentials.json \
|
||
go test -race -count=1 -run '^TestIntegrationEventConsumer(HeartbeatAndLostAck|FailureRedeliversNaturally|SlowHandlerBackpressure)$' -v .
|
||
```
|
||
|
||
缺少隔离服务或凭据时测试会跳过,跳过不能记作通过。标准 `make integration` 会在下一次完整回归中自动包含该用例。
|