perf: batch gateway submits and isolate callbacks

This commit is contained in:
hectorzhao
2026-08-25 11:39:59 +08:00
parent c6f11014d6
commit 761c123b65
29 changed files with 1912 additions and 193 deletions
+72
View File
@@ -3874,3 +3874,75 @@ git diff --check
- 通道禁用行为通过:仅禁用`LGST-M-P`时,消息`MSG-fc4a6384-3dfd-4252-bc5b-855e4e881a1a`自动选择`LGST-M-B``delivered`;主备同时禁用时,消息`MSG-5bf5960f-cfc1-4409-a6bc-80e6969ad827`最终为`failed/ROUTE`且供应商提交0条。两通道均已恢复`active`
- 通道组补发通过:模拟`LGST-M-P/SUP001`对消息`MSG-3c2ad6ea-9b45-435c-8833-7dbf7bf28ebd`返回Submit结果码8,首条提交记录为`rejected`;平台随后在`LGST-M-B`创建带`retryOfSubmitRecordId`的第二条提交,状态`accepted`,消息最终`delivered`。模拟器已恢复普通配置,6条通道连接均为`connected`
- 最终恢复审计:API及API/Worker/Gateway/PostgreSQL/Redis/MinIO服务健康;10个隔离应用全部`active`、接口全部开启、单价均0、模板模式均`direct_send`;10个签名审核/汇总报备均通过,60条签名通道报备任务全部`approved`6个LGST通道全部`active/connected`;临时风险规则0条;Inbox仅有`completed`状态;专项窗口Worker严重错误筛查0条。
## 2026-08-24 第四阶段后续优化第1步:现状复核与恢复准备
- 本地`HEAD``origin/main`均为`c6f11014d61a8627ae311098ef81d89dd099ffaa`。既有`api/tsconfig.build.tsbuildinfo``api/tsconfig.tsbuildinfo``tsconfig.tsbuildinfo``outputs/``pnpm-lock.yaml`、空文件`=`以及本轮接管时已存在的`tmp_generate_ui_drafts.py``tools/local/seed-screenshot-materials.mjs`均未修改、删除或纳入本轮范围。
- 测试环境运行标记仍为`90345fba22e3ae183e1edb4fdae718fb7cb2d963+workspace.p4progress.d82933c344ec`API、Worker、Gateway、安全代理、PostgreSQL、Redis、MinIO和Nginx均activeAPI健康、Redis PONG。数据库约1348MB、92条已完成migration、11/100连接、0等待锁、0 idle in transactionInbox只有36968条completed。10个隔离应用均active/接口开启/单价0,测试企业余额/授信为`16142576/0`
- 两条Gateway Stream的消费者均为1、`pending=0/lag=0`。BullMQ `sms.send.queue`为wait/active/failed/delayed均0`gateway.submit.queue`保留76984条wait,而同口径命令Stream已经完整消费,作为后续双发布职责梳理的当前证据,本步未清理或改写任何队列。
- 当前`pg_stat_statements`未安装且未加入`shared_preload_libraries`,记录为第2步可观测性准备项,本步未修改PostgreSQL扩展或配置。隔离供应商模拟器`100.91.249.119:17900`当前不可达,六个LGST连接状态均为failed且最后心跳停在2026-08-21;平台和数据库服务正常,但后续真实发送/压测前必须先恢复模拟器并确认6/6重连。
- 已创建root专属恢复目录`/opt/cmpp-platform-backups/phase4-step1-20260824T020501Z`,权限700。包含129MB `database.dump`、183MB `runtime-source.tar.gz`、48KB `system-config.tar.gz`、运行标记、服务状态、PostgreSQL版本、92条迁移清单及内容目录;`pg_restore --list`识别818项,源码归档内运行标记一致,全部SHA-256复核通过。数据库/源码/系统配置SHA-256分别为`5b6aec796314947b44d7d6323665036927f326994e0f598f32559a06802b03c9``7be9da3a51a11048bfdc43b4923285bd7e34a07b8a95f7b983bf92735d525d6a``1de39e5dbf4a699123c9f2dab9ffae85092c8bd194c0e7f00e630d51257132be`。备份后磁盘仍剩62GB,服务、API、Redis和两条Stream复核正常。
- 本步没有修改业务代码、数据库业务数据、通道配置、余额、客户连接或预生产环境,没有发送短信、部署或压测。第1步完成;进入第2步前的显式前置条件为恢复隔离供应商模拟器并确认6/6连接。
## 2026-08-24 第四阶段后续优化第2步:P0可观测、测试环境发布与正价诊断
- 恢复本地隔离供应商模拟器并通过Tailscale Serve将测试机到`100.91.249.119:17900`的访问转发到本机回环仿真器;重启测试Gateway后平台和模拟器均确认6/6连接。测试结束模拟器继续运行且6连接在线;未触达预生产或真实供应商。
- 测试机已有`postgresql-contrib``pg_stat_statements.so`,无需联网安装新包。新增`/etc/postgresql/16/main/conf.d/20-pg-stat-statements.conf`,设置`shared_preload_libraries='pg_stat_statements'`、max10000、track=all、track_utility=off并创建扩展;PostgreSQL重启后扩展、预加载、视图读取均通过,未调整`max_connections``work_mem`
- 发送Worker增加固定低基数分段直方图、BullMQ六状态、Worker槽位、处理结果和数据库客户端池`max/total/idle/waiting`Prisma继续使用原API/Worker池上限,仅改为显式持有同一个pg Pool以读取原生计数。指标不含手机号、企业、应用、通道、消息或任务ID。API全量42套498项、SendChain 122项、相关专项124项、TypeScript正式构建和`git diff --check`通过。
- 发布前恢复资产`/opt/cmpp-platform-backups/phase4-step2-20260824T023615Z`包含128MB PostgreSQL custom dump、181MB运行目录、56KB系统配置、恢复说明、迁移/服务清单及测试配置快照;`pg_restore --list`、两份tar目录和全部SHA-256通过。基础包/工作区补丁SHA-256分别为`d0f3311830932e3ebb4e3aea3a7bb6a9136f5acce73c9e7dd6e327953e35a24a``045215c9a9ac3c2a09a8a2402cdb7a1f3d998deb74ff9fdee6e7e266b03af0da`;排除`outputs/``pnpm-lock.yaml`、空文件`=``*.tsbuildinfo`
- 仅发布到`100.93.204.60`测试环境,运行标记为`c6f11014d61a8627ae311098ef81d89dd099ffaa+workspace.phase4step2.045215c9a9ac`92条migration无待执行项,部署安全门禁、API/Worker/Gateway/PostgreSQL/Redis/MinIO/Nginx及回环metrics均健康。预生产未发布、未回退、未压测。
- 正价smoke生成9条,9/9受理、P50/P95/P99=`34/54/54ms`,计费charged 9笔共2925金额单位;Worker 11个阶段count均为9,数据库池waiting为0。客户连接同时ACK了2483条历史pending回执,因此该回执数不作为本轮新增回执证据,随后重置`pg_stat_statements`和Worker指标再进入压力档。
- 首次100档因测试库没有`PhoneCarrierRule`,仿真联通/电信号默认归为移动,只压到移动主备;2999条生成、2997个SubmitResp、2个缺失,257次客户端节流,P99=1773ms,按停止线不升档。该轮仍给出关键对照:两个会话热点下`submit_transaction`累计669.331秒、Worker池waiting峰值38、开放会话UPSERT累计557.234秒。
- 快照后临时增加只匹配`1380028/1300028/1890028`的三条运营商规则并重启Worker,修正后的六通道100档为2999/2999受理、零拒绝/节流/连接错误,P50/P95/P99=`31/68/233ms`;移动/联通/电信=`998/996/1005`。六供应商账号各收到588至612次提交尝试;2999个唯一号码的首次供应商提交从`02:55:20.074Z``02:56:53.068Z`,覆盖`92.994秒`、约`32.25条/秒`,完整100条/秒目标仍失败,未执行200/300/500。
- 六通道诊断阶段均值:message_load约22.7ms、phone_routing约18.5ms、route_lookup约33.5ms、signature_candidates约7.0ms、signature_final_check约6.8ms、rate_limit约6.8ms、submit_transaction约47.4ms、BullMQ发布约7.1ms、Stream发布约6.9ms、task_progress约18.2ms、total约175.1ms。180秒采样峰值为Worker in_flight24、数据库池total32/waiting3、PostgreSQL未授予锁20;结束均归零。
- `pg_stat_statements`进一步确认正价入口企业账户`pg_advisory_xact_lock`累计390.932秒/587次、均值665.983ms;开放会话`CmppSubmitSession` UPSERT累计32.293秒/3616次、均值8.931ms。P1应先治理企业账户批次锁竞争和六个开放会话热点行,再处理路由、号码回写、任务进度与重复Gateway入口;本步不执行P1代码优化。
- 日志复核发现两个非本次指标代码引入但需后续处理的相邻问题:部署后定时报表刷新有1次5秒交互事务过期;压力客户端连接关闭/重建竞争触发`CmppDownstreamConnection`的P2025/P2002。发送Worker无uncaught/fatal,当前窗口6006个Inbox全部`completed/attempts=1`,服务、连接和Stream最终恢复正常;本步只记录证据,不扩展为业务修复。
- 本轮精确6006条正价消息(smoke 9、单运营商误测2998、六通道2999)冻结/释放各6006笔、金额1951950;正式charged 5991笔/1947075,退款73笔/23725SmsBillingRecord最终charged5918/refunded73,当前样本净扣1923350,账务链一致。测试窗口还处理了103条历史消息退款,因此账户从16159476到14269601的总变化以窗口全量账务净额核对,不能只用本轮MessageId计算。
- 最终已恢复10个隔离应用为active/接口开启/单价0,三主通道priority10/非备用、三备priority20/备用、weight100,删除3条临时运营商规则并重启Worker6通道active/connected,两条Stream pending/lag均0,数据库0 idle-in-transaction、0锁等待、0未授予锁,8项服务active。真实消息、账务、回执和操作日志保留审计;受保护工作区文件未纳入发布或删除。
## 2026-08-24 第四阶段后续优化下一步:P1低风险数据库往返收敛
- 实施四项低风险收敛:CMPP单号码任务提交按已知状态直写,结果/回执/超时用单条`UPDATE ... FROM`读取唯一消息状态并直写;路由、在线连接与签名运营商报备合并为一次候选查询并删除最终二次报备查询;Worker首次读取后复用开放会话ID,事务不再逐短信更新`submitTotal`;确认Go Gateway只消费Redis Stream且具备PEL自动认领、逐条ACK、结果Outbox和死信,发送Worker停止向无人消费的`gateway.submit.queue`同步写副本。Redis Stream发布前的跨介质崩溃窗口尚无独立PostgreSQL Outbox扫描器,明确留作P2残余风险。
- 本地API全量42套500项、SendChain 124项、TypeScript正式构建和`git diff --check`通过。两次部署前分别建立`/opt/cmpp-platform-backups/phase4-p1-20260824T033000Z`和最终恢复点`/opt/cmpp-platform-backups/phase4-p1-final-20260824T034900Z`;最终恢复点包含154MB PostgreSQL custom dump、2.4MB精简运行源码和56KB系统配置,`pg_restore --list`、两份tar及SHA-256全部通过。最终发布包SHA-256=`eb07c9fb5dfff3152fed52574895cd4308b69818e78685d6aad5649507ec4521`,仅部署测试机,运行标记=`c6f11014d61a8627ae311098ef81d89dd099ffaa+workspace.phase4p1.eb07c9fb5dff`92条migration无待执行项。预生产未修改。
- 最终正价smoke 9/9受理,P50/P95/P99=`29/33/33ms`。最终六通道100档2999/2999受理,零拒绝、零节流、零连接错误,P50/P95/P99=`33/77/179ms`;三运营商=`998/996/1005`,六通道提交尝试分别为主`998/996/1005`、备`182/178/166`。2999个唯一号码首次供应商提交从`03:51:44.049Z``03:53:23.989Z`,覆盖99.940秒、约30.00条/秒,低于P0对照32.25条/秒,完整100条/秒仍失败,按停止线未升200/300/500。
- 最终Worker阶段3008个样本(smoke+100档)平均:message_load约18.5ms、phone_routing约16.4ms、route_lookup约32.4ms、signature_candidates约0.004ms、rate_limit约5.4ms、submit_transaction约26.8ms、Stream发布约5.5ms、task_progress约17.9ms、total约123.1ms;相比P0总耗时175.1ms下降约29.7%,提交事务和重复签名/路由往返明显下降。应用产生的单任务状态`GROUP BY`为0,开放会话`submitTotal`更新为0,Bull遗留wait从测试前到结束始终84119。
- 剩余决定性瓶颈为正价同企业计费`pg_advisory_xact_lock`,累计373.373秒/841次、均值443.963ms,远高于其余SQL;因此P1只降低Worker单条耗时,未提升完整供应商吞吐。最终样本消息2999/MessageId2999/号码2999均唯一;当前消息delivered2895、failed42、submitted62,提交accepted3142/rejected73/timeout310。冻结/释放各2999笔974675,扣费2990笔971750,退款25笔8125SmsBillingRecord当前charged2965笔963625/refunded25笔8125,账务一致。
- 测试后10个隔离应用全部恢复active/接口开启/单价0,3条临时运营商规则删除,6个供应商通道保持connected;命令/结果Stream均pending0/lag0Bull遗留wait84119未增长,数据库idle-in-transaction0、未授予锁0API/Worker/Gateway/PostgreSQL/Redis/Nginx均active且发布窗口无error级journal。真实测试消息、账务和回执保留审计;未提交、未push,受保护的`*.tsbuildinfo``outputs/``pnpm-lock.yaml`、空文件`=`及其他并发产物未删除或纳入发布。
## 2026-08-24 第四阶段P2:正价计费并发锁治理与Worker微批取舍
- 发布前恢复资产位于`/opt/cmpp-platform-backups/phase4-p2-20260824T101000Z`PostgreSQL custom dump 161MB、`pg_restore --list` 835行、精简源码1.4MB、系统配置2KB,两个tar可解包且SHA-256完整。最终测试环境标记为`c6f11014d61a8627ae311098ef81d89dd099ffaa+workspace.phase4p2final.879a234fbc86`,仅发布`100.93.204.60`,预生产未操作。
- 正价入站批量持久化仍保持全部账务与业务行同事务;仅将同企业`tenant-account` advisory lock移到事务末尾账务段。最终正价六通道50档该锁598次累计3.241秒/均值5.420ms,相比P1的373.373秒/841次、均值443.963ms,累计下降约99.1%、均值下降约98.8%。
- Worker 5ms/最多20条的消息加载微批曾部署实测,去除最慢项栅栏后仍只有约22.20条/秒,低于P1对照,因此已回退且最终发布不包含该负优化。最终代码只保留计费锁缩短,PostgreSQL Submit Outbox、批量路由与批量提交不再执行。
- 最终六通道正价50条1499/1499受理,零拒绝/节流/连接错误,入口P50/P95/P99=`31/77/227ms`。1499个唯一号码首次到达供应商从`10:37:44.510Z``10:38:53.564Z`,覆盖69.054秒、约21.69条/秒,50档失败,按停止线未执100或更高档。
- 最终样本MessageId/号码均1499个且唯一,客户单价min/max均325;冻结/释放各1499笔487175charged1496笔486200,最终失败退费21笔6825`SmsBillingRecord` charged1475笔479375/refunded21笔6825,净扣一致。所有压力运行均为325正价,没有0计费压测。
- 结束后根据发布前CSV快照恢复10个隔离应用单价为0,删除3条临时号段规则;这是环境还原,还原后未再压测。API/Worker/Gateway/PostgreSQL/Redis/Nginx均active,六供应商连接在线,BullMQ wait/active和两条Stream pending均0。代码未提交、未push,受保护产物未纳入发布。
## 2026-08-24 第四阶段发布前收尾回归
- 仅在`100.93.204.60`测试环境和本地隔离供应商模拟器执行,运行标记仍为`c6f11014d61a8627ae311098ef81d89dd099ffaa+workspace.phase4p2final.879a234fbc86`;预生产未操作。恢复点继续使用`/opt/cmpp-platform-backups/phase4-p2-20260824T101000Z`
- 正价主流程使用`920001`、新号码`13877780000`和单价325SubmitResp为0、延迟15ms;消息`MSG-6b537761-9a1c-47eb-88d3-fe5e1d7d33f9`最终`delivered`,主通道Submit accepted、真实`DELIVRD`回执闭合,消息/计费记录单价和金额均325,账户生成`charged -325`流水。结束后单价回读为0。首次因远程SQL引号导致单价未生效的0价消息明确作废,不作为计费证据。
- 上行使用同一真实MessageId从测试机内部Gateway事件入口注入,`SmsUplinkMessage cmt75bszh0qjy6vletv06f4pc``messageId 精确匹配`关联应用和原消息;客户连接上线后普通Deliver得到ACK,`CmppDownstreamDelivery`最终`delivered`。Gateway原始CMPP Deliver解析继续由全量Go测试覆盖。
- 当前版本拦截复测通过:签名未审核`MSG-c52b65a8-2451-465f-ac80-83779d78e341``failed/SIGNATURE`;模板未报备`MSG-137ae451-18e2-401f-b908-a4e4db0175ad``failed/TEMPLATE`;余额不足`MSG-1287c06b-3ecb-4fde-be1c-401636a2505c`按325计算并为`failed/BALANCE`;号码频次同号第一条delivered、第二条`MSG-6bec92fd-8eab-4450-afbf-555c292a2150``failed/RISK`且命中阈值1/实际2。四种失败均供应商提交0,客户失败回执已生成,临时状态和规则均恢复。
- 应用接口关闭、应用`inactive/deleted`、企业`inactive/deleted`五次CMPP bind均返回状态3且未进入提交;应用、企业和接口均已恢复。
- 通道报备和禁用复测通过:移动主备报备临时pending时`MSG-44c2b749-62fc-47f7-a200-9ed74d2f1ff7``failed/ROUTE`且供应商提交0;仅主通道inactive时`MSG-d256c8fc-e74f-4260-9fa6-595a37b16e17`自动选`LGST-M-B`并delivered;主备都inactive时`MSG-598ea5de-da7f-4c24-ac4d-728e12629489``failed/ROUTE`且供应商提交0。
- 通道组补发在模拟器6/6且数据库六通道均`connected/currentConnections=1`后执行:`MSG-0a91d27a-0d39-4377-a57d-fa98e869d2d9``LGST-M-P`结果码8/rejected,随后`LGST-M-B`产生带`retryOfSubmitRecordId`的accepted提交并最终delivered。切换模拟器后未等待数据库连接状态的第一次试验只有主通道拒绝,明确判为夹具无效轮,不作为产品失败。
- 最终恢复回读:10个隔离应用全部active、接口开启、单价0、模板模式direct_send;隔离企业active16个签名审核均approved10个签名汇总报备approved60条通道报备任务approved6通道active且connected;临时规则0Inbox pending0;两条Stream pending/lag均0BullMQ wait/active均0;数据库锁等待和idle transaction均0;六个核心服务active,普通模拟器6/6连接。
- 新增`docs/phase-4-send-pipeline-redesign.md`,说明原BullMQ Worker微批边界、跨介质一致性和回调资源争用问题,并提出PostgreSQL Submit Outbox、批量路由持久化及回调池隔离方案。当前不实施该重构。
- 发布门禁复跑:API全量42套500项通过,TypeScript正式构建通过。pnpm包装器首次在测试启动前因既有`msgpackr-extract`未批准构建脚本退出;未修改依赖或锁文件,随后直接使用已安装的Jest/TypeScript入口完成验证。`git diff --check`与最终Git范围检查另行执行。
## 2026-08-25 PostgreSQL Submit Outbox发布与正价压测
- 仅部署测试机`100.93.204.60`,标记`c6f11014d61a8627ae311098ef81d89dd099ffaa+workspace.phase4outbox-live.20260825`;恢复资产`/opt/cmpp-platform-backups/phase4-outbox-20260825T094000Z`已验证,预生产未操作。
- API 42套502项、Gateway全包测试、TypeScript构建和`git diff --check`通过;迁移已应用,API/Worker/Outbox/Gateway/PostgreSQL/Redis/Nginx active。
- 正价阶梯:20 TPS=20.46/s、计费6467530 TPS=29.97/s、计费97175;三运营商50 TPS=33.07/s、计费162175。所有档MessageId/submitId唯一,补发均关联retryOf,队列和锁干净。
- 50 TPS停止线未通过,未执行100/200/300/500。临时号段规则已删除,10个测试应用单价恢复0;最终Outbox published=2172、payload差异0、重复submitId=0、Inbox非completed=0、双Stream pending/lag=0。
## 2026-08-25 批量路由持久化、独立回调进程与正价复压
- 发送Worker新增最大32条、等待3ms的有界聚合批次:批量读取消息、号段、路由/连接/签名报备,按消息完成实时约束和通道限速;首次提交以一个短事务批量创建`SmsSubmitRecord`、集合式更新消息、批量创建`GatewaySubmitOutbox`。重试、拒绝和异常仍走原逐消息幂等状态机。
- 新增回环`cmpp-gateway-callback`进程,独立12槽数据库池,专门处理Submit结果、分片结果、回执、上行、受限协议日志和死信;客户HTTP Webhook仍在主API异步Worker。Gateway连接状态控制继续写主API,供应商事件写回调进程。回调管理Controller未加载,端口仅监听`127.0.0.1:3001/9468`
- 初次smoke因连接状态控制误发到回调端点而全部`failed/ROUTE`,供应商提交0、计费0;已拆分控制面和事件面URL并复测,六连接数据库状态均为connected。该轮作为发布缺陷审计保留,不纳入容量统计。
- 修复后正价结果:smoke 9/9、账单292520 TPS 199/199、P50/P95/P99=`19/51/94ms`、账单6467530 TPS 299/299、`20/48/69ms`、账单9717550 TPS 499/499、`35/76/135ms`、账单162175。四个成功窗口合计1006条、1006笔账单、单价全部325、金额326950。
- 50档499条唯一首次供应商Submit跨度9.930秒,完整提交速率`50.25条/秒`,相对上一版同档33.07条/秒提高约52%。全部尝试/Outbox均542条且ID唯一;状态检查时delivered485、failed4、submitted10,关联补发43次。Inbox、Outbox、双Stream最终排空,数据库无等待锁、无idle in transaction,回调池`max=12,total=1,idle=1,waiting=0`
- 测试环境最终标记`c6f11014d61a8627ae311098ef81d89dd099ffaa+workspace.phase4batchcallback.callback-surface.599393bb6233`;恢复资产为`/opt/cmpp-platform-backups/phase4-batch-callback-20260825T025611Z`。10个隔离应用单价恢复0,三条临时号段规则删除,真实计费事实保留;预生产未操作,未执行100/200/300/500档。