Files
orbit/docs/reports/phase-6-slow-consumer.md

42 lines
3.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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` 会在下一次完整回归中自动包含该用例。