perf: batch paid CMPP accounting and weighted routes

This commit is contained in:
hectorzhao
2026-08-21 10:25:40 +08:00
parent 0176aa6952
commit 487b5282a6
12 changed files with 219 additions and 40 deletions
+7
View File
@@ -1164,3 +1164,10 @@ global,不能错误归入client。`client-signature-*`、发送页、企业认
- 500条/秒第三阶段继续留在`send-inbound-entry`编排边界,但将批次只读风控快照下沉到`RiskReviewService.evaluateTasksBatch`,将频控原子批量预留下沉到`PhoneFrequencyService.reserveBatch`。Inbox编排层只负责批次分组、日限额锁顺序、正常三表批量持久化、幂等入队与逐条租约结算;付费及异常状态机仍委托原单条路径,避免形成第二套计费/审核领域模型。
- 批次锁顺序固定为:领取事务只锁Inbox后立即提交;日限额事务按applicationId排序锁`SmsApplicationDailyUsage`;频控按tenant/application分组且规则优先级顺序更新号码状态;三表事务不持有前两类锁,Redis/BullMQ发布永不位于数据库事务内。该顺序用于限制死锁面并允许单批失败后按每条稳定幂等键恢复。
- 容量参数继续归进程组装层:Inbox业务槽、BullMQ发送槽、Gateway供应商槽和结果Outbox槽分别有界、分别观测。代码模块不得假定测试环境参数就是生产默认值;生产调优必须重新基于PostgreSQL连接预算、六通道TPS/窗口和回调承载证据。
## 2026-08-21 第四阶段模块边界
- `send-inbound-entry`负责编排正价批次短事务;账户固定锁序、总额覆盖、逐短信冻结幂等键留在PostgreSQL一致性边界,不迁入Redis。
- `billing.service`集中维护账户锁和流水,`settleFrozenCharge`把释放/扣费合并为一个事务;`send-accounting`只编排消息计费状态。
- `send-chain.helpers`提供无副作用的优先级、主备和稳定weight选择;提交服务只提供消息稳定键与真实在线/报备候选,不保存进程内轮询状态。
- Gateway既有Submit池与结果Outbox继续独立有界;先以正价六通道实测定位容量,只有证据证明单条回调仍触发停止线时才扩展批量回调协议。
@@ -2129,3 +2129,10 @@
- 正常单号码、零计费短短信允许走批量快路径:日限额按应用锁定并为每个Inbox请求写独立幂等预留,风控只共享只读输入,号码频控在同一事务批量更新状态并逐请求保存决定,任务/API请求/消息三表在一个短事务批量创建,BullMQ使用消息ID作为幂等Job ID批量入队。
- 付费短信、重复号码、黑名单/格式拒绝、模板人工审核、引流匹配歧义、既有消息恢复及其他异常分支必须回到原逐条状态机;不得为压测降低计费、风控、频控、模板、签名或失败回执规则。批量路径在数据库提交后、队列发布前崩溃时,逐条恢复必须利用稳定任务号、请求号、MessageId和预留键补齐,不得重复计量或创建消息。
- 批量Worker指标增加`worker_claim/reference_preload/daily_quota`固定低基数阶段,并继续记录`risk_frequency/message_persist/queue_publish`;配置必须显式启用批处理并使用正整数批次大小。验收仍以真实PostgreSQL、Redis、BullMQ和隔离供应商证据为准,不能用零计费压测结果外推付费链路吞吐。
## 完整处理500条/秒第四阶段:正价计费与供应商并行(2026-08-21)
- 普通CMPP短短信批量路径必须支持正单价:按企业固定锁序一次校验批次总金额、一次更新余额,并为每短信写独立幂等冻结流水;任务、请求、消息与冻结流水同属一个短事务。余额加授信必须覆盖所需金额,不能只判断大于零。
- 供应商接受后,释放冻结与正式扣费在一个账户锁事务内保留两条审计流水;零金额不创建AccountTransaction。拒绝、超时、重投和最终失败继续沿用逐短信幂等释放、扣费和退款。
- 同通道组内在线、已报备、同地域、同最低优先级且非备用的通道按weight和稳定消息键分流;备用、离线及更低优先级不抢占。只有显式配置为同优先级非备用的通道才参与主动双活。
- 压测使用隔离测试企业、真实PostgreSQL账务、单价`0.0325元/计费条`、三运营商混合号码和六个模拟供应商账号;逐档核对消息、冻结/释放/扣费/退款、SmsBillingRecord、通道分布、队列和数据库。临时单价与主动双活配置须先快照、测试后恢复。
+13
View File
@@ -4772,3 +4772,16 @@ npm run verify:phase8
| TC-CMPP-500-P2-006 | 100→200→500完整链阶梯 | 使用全新测试号段、隔离六通道模拟器,逐档注入并等待全部队列排空 | 每档报告入口实际速率/分位、Inbox完成、各队列峰值与排空、供应商阶段和数据库对账;500档只有入口及完整链均达到500条/秒且零丢重才通过 |
执行记录(2026-08-20,测试环境):P2-001至004由121项SendChain专项、真实PostgreSQL修复后低负载9/9及100条/秒2998/2998受理覆盖;首次真实执行发现并修复`jsonb_build_object`参数类型错误,该无效轮未写Inbox。P2-005使用API/Worker池48/32及96/96/128/32四类有界业务槽,数据库压后无idle-in-transaction。P2-006在100条/秒入口通过但完整链失败:Inbox约57.5条/秒、双Stream完整排空约22.0条/秒,且后台API回调超时;按停止线未继续200/500,因此第二阶段仍不通过完整500条/秒目标。
## TC-CMPP-500-P4 正价计费与六通道并行
| 用例 | 场景 | 预期 |
| --- | --- | --- |
| TC-CMPP-500-P4-001 | 同企业正价短短信批量入站并重放 | 一次账户余额更新;每短信唯一`:freeze`流水;任务/请求/消息金额正确;重放不重复冻结 |
| TC-CMPP-500-P4-002 | 余额加授信小于批次或单条金额 | 不得透支;批次安全回退且只发送余额覆盖的短信 |
| TC-CMPP-500-P4-003 | 正价短信Submit接受及Outbox重放 | 一个账户锁事务生成released/charged;余额净值不重复变化;SmsBillingRecord唯一charged |
| TC-CMPP-500-P4-004 | 零价短信Submit接受 | 保留业务结果但无0金额AccountTransaction |
| TC-CMPP-500-P4-005 | 两个同优先级非备用通道与一个备用通道 | 稳定weighted分流只覆盖两个主动通道;排除已尝试通道后可安全切换;备用不抢占 |
| TC-CMPP-500-P4-006 | 三运营商、六通道、325金额单位阶梯压测 | 每档入口/Inbox/供应商/回执/账务对账一致,双Stream和数据库最终稳定排空;失败即停止升档 |
| TC-CMPP-500-P4-007 | priority与normal并发积压 | priority保持明确服务能力且normal最终不饿死 |
| TC-CMPP-500-P4-008 | 测试配置治理 | 单价、账户与组项目先快照;临时主动双活和单价测试后恢复;预生产和凭据不变 |
+7
View File
@@ -3833,3 +3833,10 @@ git diff --check
- 100档注入结束时命令Stream`pending=128/lag=922`、结果Stream`pending=32/lag=31`,数据库瞬时`idle in transaction=3/waiting active=12/not-granted locks=7`;约25秒后数据库恢复0/0/0、双Stream恢复0/0。自开始至最终排空约87秒,按2998条折算完整下游约34.5条/秒,低于100条/秒;最终消息delivered2770、failed64、submitted164,隔离供应商本档累计提交尝试3281、accepted3226、rejected55、无回执69,错误0。
- 因100档下游队列在负载期持续增长且完整链不足100条/秒,严格按停止线没有执行200/300/500档。第三阶段结论:入口100条/秒和业务Inbox接近实时排空通过、相较第二阶段约57.5条/秒显著改善,但业务Worker500条/秒与完整链500条/秒均未证明;第四阶段仍需供应商六通道真实并行、发送链/回调独立工作池后再升档。测试应用单价为0,本结果不得外推正单价批量计费吞吐;正单价继续走已回归的逐条原子账务路径。
- 全程仅使用`100.93.204.60`测试环境和`100.91.249.119:17900`隔离供应商模拟器,没有发送、补发或重投真实短信,没有修改通道账号、密码、启停状态、企业余额或客户连接。预生产只读标记保持`433b2ee5...+gateway-v2.cd7bb8d05e7b`,未发布、未回退、未压测;受保护的`tsbuildinfo``outputs/``pnpm-lock.yaml`和空文件`=`继续排除提交、不删除、不归因。
## 2026-08-21 完整处理500条/秒第四阶段(实施中)
- 接管复核:本地`HEAD=0176aa6952f1e71a50a8f49eeaa64e307da02370``origin/main=c4f36fc50d7906dfb2f97c881e9ea43c6a64c370`;测试环境仍为`52028b9b...+workspace.p3.7c14cd5f197a`,预生产只读标记仍为`433b2ee5...+gateway-v2.cd7bb8d05e7b`。测试机六连接在线、双Stream 0/0、数据库无等待锁和idle in transaction。
- 10个隔离应用仍为单价0、同企业余额1/授信0;移动主备各200条/秒,联通/电信主备各150条/秒,窗口32。组项目为主10/备用20,默认只能三主主动承载,六连接在线不等于六通道并行。
- 已实现正价Worker批次、覆盖本次金额的余额判断、单事务释放/扣费、零价免账户流水,以及同最低优先级非备用通道的稳定weighted分流;默认主备语义不变。API正式编译和Billing/纯策略/SendChain三套143项通过。
- 部署、恢复资产、测试充值、临时六通道主动双活、smoke及阶梯结果待补记;所有临时配置只允许在测试环境先快照后变更并在测试后恢复。