ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

短信业务流程分析:状态机建模与回执追踪实践

短信业务流程分析:状态机建模与回执追踪实践 简介这份PPT从短信业务的基本概念入手系统梳理了SMS短消息服务的存储转发机制以及短信中心SMSC在接收方关机或无信号时暂存消息、待恢复后再投递的完整流程。内容面向通信工程、管理信息化方向的开发者、运维人员及初学者适合作为理解短信底层协议和基础编码的快速入门资料。资源包为单个pptx文件大小1.16MB结构紧凑便于直接阅读。已有171人学习。PPT重点对比了Text模式与PDU模式的区别指出Text模式无法处理中文而PDU模式支持7-bit、8-bit及UCS2三种编码方式同时详细拆解了PDU格式中从短信中心地址长度到用户数据的13个字段含义并汇总了ATCMGF、ATCMGL、ATCMGS等常用指令。最后通过向8613602433649发送“工作愉快”的实例逐步演示短信中心号码移位、手机号码处理、Unicode转换及PDU封装过程能帮助读者快速掌握短信发送编码技巧为开发或调试相关系统提供实用参考。1. 为什么短信业务流程分析总卡在回执这一步做短信业务流程分析第一张图画出来往往就是错的因为它被画成了一条从业务系统到手机的单向直线。实际上短信是一条典型的异步确认型业务链路业务系统发起请求短信平台受理并选择通道网关用运营商协议提交SMSC 寻址下发手机收到后再由运营商返回一条状态报告RPT流程才算关闭。任何一个环节都有独立的超时、重试、失败分支而最容易让分析失真的是最后一跳——回执。很多团队把平台受理成功当作发送成功来统计导致 U1 这张图看起来全绿真实送达率却低得没法看。这条链上真正值得关注的是状态报告何时回来、以什么代码回来、是否超时未归。把回执当成一等公民来建模流程分析才成立。这篇文章从组件职责、状态机建模、代码级跟踪讲到指标口径和 PPT 页面叙事适合刚接手消息系统梳理、稳定性治理或者做运营商通道切换评估的人。2. 短信业务流程分析从组件职责到状态机的核心建模2.1 短信链路四大组件谁发起、谁路由、谁下发、谁回执短信链路如果不把组件边界切清楚后面画流程图、设超时时间、定重试策略都会扯皮。我一般会把整条链路切成四个逻辑组件组件职责典型实现/协议故障表现业务侧发起发送请求、接收回执回调HTTP API / MQ 异步通知接口超时、回调丢失短信平台鉴权、模板校验、频控、通道选择、重试调度自研网关常挂在 Spring Cloud 或 Dubbo 体系下限流误伤、路由表陈旧短信网关用运营商协议封装消息维护长连接和消息序号CMPP / SGIP / SMGP 协议适配层连接闪断、sequence 错乱运营商侧与终端寻址 HLR、下发到手机、生成状态报告SMSC / HLR / MSC关机、欠费、黑名单回执延迟或缺失这里面最关键的分界点是同步和异步的边界。业务侧调短信平台的 HTTP 接口拿到 200 响应只表示平台受理了这条消息并不等于手机收到了。从短信平台往下的每一跳都是异步的最终结果要靠回执反向通知。所以做分析时第一步不是画流程图而是定出一个原则受理状态和终态状态必须分开记账否则任何指标都会失真。协议层也值得注意。CMPP 对应中国移动SGIP 对应中国联通SMGP 对应中国电信三者消息结构不同但语义基本一致都有一个 Submit 操作用于下发有一个 Deliver 操作用于回传状态报告。分析时不用拘泥于协议字段差异先抽象成提交—回执两件事再看具体字段映射。2.2 用状态机刻画短信消息的生命周期短信消息不能只用成功/失败两个布尔字段描述因为消息会经过多个中间态。完整的生命周期可以建模为INIT初始→ ACCEPTED平台受理→ SUBMITTED网关确认→ DELIVERED / FAILED终态另外还有 UNKNOWN回执超时未归和 RETRY_WAIT等待重试。当前状态触发事件下一状态事件来源INIT业务提交ACCEPTED平台受理成功ACCEPTED网关返回 SubmitRespSUBMITTED网关确认收到SUBMITTED收到回执 DELIVRDDELIVERED运营商回传SUBMITTED收到回执失败码FAILED运营商回传SUBMITTED等待回执超时RETRY_WAIT平台定时器RETRY_WAIT重试提交SUBMITTED平台重新下发这里有一个容易被忽略的重点SUBMITTED并不是终态它只代表网关收下了消息不代表手机收到了。很多流程分析图把提交网关成功画成绿色结束节点这是最常见的错误画法。终态只有 DELIVERED、FAILED 和 UNKNOWN 三种其中 UNKNOWN 是回执丢失或超时的兜底状态必须单独归类不能并入 FAILED。用代码来表达状态机会更严谨。下面是一个精简的状态机模型class SmsMessage: def __init__(self, msg_id, phone): self.msg_id msg_id self.phone phone self.state INIT self.ts {} def transit(self, event, ts): mapping { (INIT, submit): ACCEPTED, (ACCEPTED, gateway_ack): SUBMITTED, (SUBMITTED, rpt_delivrd): DELIVERED, (SUBMITTED, rpt_fail): FAILED, } key (self.state, event) if key not in mapping: print(funexpected event {event} at state {self.state}) return False self.state mapping[key] self.ts[self.state] ts return Truetransit 函数里不允许跨状态跳跃比如在 INIT 状态直接收到rpt_delivrd说明回执和提交的关联出了问题。真实系统里经常出现这种日志原因往往是 msg_id 生成规则不唯一或者回调错乱。用状态机的好处就是能快速把这些非法事件捞出来。2.3 CMPP 原语与状态机节点的映射关系如果底层是 CMPP 协议状态机节点和协议原语可以直接映射。分析时把协议层事件翻译成业务状态就能在日志里统一口径。业务状态CMPP 操作关键字段INIT构造 Submit 请求MsgId、SrcTerminalID、DestTerminalIDACCEPTED收到 ConnectResp 和 SubmitRespMsgId、PkTotal、PkNumberSUBMITTEDSubmit 成功并启用了回执MsgId、RegisteredDelivery1DELIVERED收到 DeliverStatDELIVRDMsgId、DoneTime、StatFAILED收到 DeliverStat失败码MsgId、ErrCode、Stat映射时最常踩的坑是 RegisteredDelivery 位没有置 1导致平台提交消息后永远等不到 Deliver。这种情况在流程分析里表现为SUBMITTED 之后状态卡住回执率为 0但运营商侧实际已经下发。把映射关系列成表格放到文档里能在一开始就暴露这类配置遗漏。3. 短信业务流程落地的代码级跟踪与重试参数设计3.1 用最小 Python 模型模拟从 Submit 到 RPT 的回执关联状态机建好之后下一步是模拟真实的异步回执过程。核心数据结构是一个 pending 字典负责把已提交但未收到回执的消息暂存起来等待 RPT 到达。import time class SmsTrack: def __init__(self): self.pending {} self.finished [] def submit(self, msg): msg.transit(submit, time.time()) msg.transit(gateway_ack, time.time()) self.pending[msg.msg_id] msg return msg def on_rpt(self, msg_id, stat): msg self.pending.pop(msg_id, None) if not msg: print(flate rpt for {msg_id}, already removed) return msg.transit(stat, time.time()) self.finished.append(msg) def scan_timeout(self, timeout30): now time.time() for msg_id, msg in list(self.pending.items()): if now - msg.ts.get(SUBMITTED, now) timeout: print(ftimeout msg{msg_id}, state{msg.state}) self.pending.pop(msg_id)on_rpt里的pop(msg_id, None)是回执关联的关键操作如果回执对不上 pending 里的消息说明要么 msg_id 不唯一要么回执重复到达。scan_timeout从消息进入 SUBMITTED 状态的时间开始计时超过阈值就进入超时处理但不要直接标记为 FAILED更合理的做法是先进入 RETRY_WAIT由重试调度决定是否再次提交。还有一个细节重试不是把消息状态拨回 INIT而是为原消息生成一条新的提交流水继承同一个 msg_id同时保留上一轮的状态历史。这样统计每条消息最终是否送达和该消息被提交过几次就可以同时完成。3.2 超时、重试与退避的阈值怎么定回执等待时间、重试次数、退避间隔这三个参数直接决定用户体感和通道健康度。我常用的初始参数如下参数建议值调参依据等待 RPT 超时30 秒绝大多数短信在 10 秒内回执超过 30 秒回执到达概率很低重试次数2 次超过 2 次会放大重复消息投诉运营商也会风控拦截重试间隔1s - 5s - 30s指数退避避免集中在同一秒打爆网关通道熔断条件失败率 5% 且样本数 100快速切通道保护整体到达率单连接并发上限按通道协议和建议值配置并发过高会让超时排队表面超时率飙升这里的核心逻辑是超时不等于失败。等待 30 秒没有回执可能是因为手机在信号盲区、运营商回执通道拥塞也可能消息已经下发但回执丢了。所以重试之前要区分场景如果消息尚未被网关确认可以直接重试如果已经收到运营商正在下发类状态则不应盲目重试否则会出现用户半小时内收到三条验证码的问题。3.3 链路日志里该记录哪些字段流程分析的数据基础是每条消息的完整状态轨迹。日志至少要包含以下字段并输出为结构化的 JSON{ msg_id: MSG20250110001, trace_id: 8f1e2c8a, phone: 1380000xxxx, channel: cmpp1, state_seq: [INIT, ACCEPTED, SUBMITTED], ts: { ACCEPTED: 2025-01-10 10:00:01.123, SUBMITTED: 2025-01-10 10:00:01.356 }, result: SUCCESS, err: }msg_id用于关联提交和回执trace_id用于贯穿业务系统到短信平台的调用链两者缺一不可。很多团队在日志里只记录业务订单号结果回执到达时无法反查平台内部的提交流水问题就卡在关联上。另外ts里每个状态都要打点不能只在最终结果里打一个时间戳否则状态停留时间这个核心指标根本算不出来。4. 短信业务流程的关键指标计算与问题定位4.1 五个必须坚持统计的指标口径流程分析到指标阶段最容易出现口径混乱。下面这五个指标是我在每次短信流程复盘时必看的指标计算口径健康阈值异常含义提交成功率Submit 成功数 / 业务请求总数 99%平台前置校验、鉴权或限流问题网关受理率网关 SubmitResp 数 / Submit 成功数 98%通道连接断开或协议错误回执率RPT 总数 / 网关 SubmitResp 数 95%回执回调配置缺失或运营商回执通道拥塞送达率DELIVRD 数 / RPT 总数 90%号码质量、黑名单或运营商风控拦截回执延迟RPT 到达时间 - SubmitResp 时间P95 10s运营商下发链条缓慢或短信平台处理延迟注意送达率的计算分母是 RPT 总数不是 SubmitResp 总数。如果回执率本身只有 80%那送达率即使算出来是 99%也只是已经收到的回执里 99% 是成功整体送达率实际上只有 79%。指标要分层看才能判断问题出在平台侧还是通道侧。4.2 用状态停留时间把定位范围缩小到一跳只看最终送达率只能知道好不好不能知道哪里不好。要定位到具体一跳需要统计每个状态停留时间。假设日志表里有state_seq和对应时间戳可以用下面这种查询算出各状态耗时select state, avg(extract(epoch from (next_ts - ts))) as avg_stay_sec, percentile_cont(0.95) within group ( order by extract(epoch from (next_ts - ts)) ) as p95_stay_sec from ( select msg_id, state, ts, lead(ts) over (partition by msg_id order by ts) as next_ts from sms_state_seq ) t group by state;lead(ts)取同一条消息的下一个状态时间extract(epoch from ...)把时间差转成秒。如果发现SUBMITTED到DELIVERED的 P95 远大于 10 秒问题在运营商下发链路如果ACCEPTED到SUBMITTED的耗时异常多半是平台侧的通道选择或协议适配层在排队。4.3 三类典型异常的特征与定位路径网关受理率持续偏低优先查网关连接状态CMPP 长连接是否频繁断开重连、sequence 号是否在连接重建后重置。回执率低但送达率正常优先查 RegisteredDelivery 标志位和回执路由配置这类问题与分析图上的状态断点完全一致。送达率低且失败码集中在特定枚举比如超时类或黑名单类就要按失败码分组统计把号码问题和通道问题分开向运营商提交工单。5. 把短信业务流程分析写进 PPT 的页面叙事5.1 一页一结论的页面骨架流程分析的结果要给别人看PPT 页面结构比画图技巧更重要。我的习惯是每页只回答一个问题页面标题直接用疑问句正文用图表作答附录放明细。六页的骨架可以这么拆页码页面标题核心内容呈现方式P1短信链路四段分别是谁组件边界和同步/异步分界横向泳道图P2消息从受理到回执经历了什么状态机流转与回执映射状态表 事件箭头P3超时和重试什么时候触发参数阈值与决策分支参数表 小流程图P4当前链路健康度如何五个核心指标与阈值标注指标卡 红黄绿状态P5时间到底消耗在哪一跳各状态停留时间分布横向柱状图P6下一轮要改什么按 ROI 排序的改进建议三条结论 一个责任人P5 是全篇最关键的页面因为状态停留时间分布能直接回答时间在哪这比画十张架构图都有说服力。5.2 用泳道图和时间线分布替代满屏箭头流程图的常见误区是箭头过多阅读者根本分不清主线与分支。我一般用四个泳道承载组件把一次消息的生命周期画成一条随时间的折线从业务侧发起落到平台跳到网关再指向运营商最后回执返回。哪个环节的回执缺失折线就断在哪个泳道的边界汇报时一句话就能说明白。时间线分布建议用直方图展示回执延迟横轴是延迟秒数纵轴是消息量左峰代表健康基线的送达群体右拖尾是需要继续排查的通道质量或号码问题。做图前先把回执延迟的阈值画成竖线这条线取 P95 的日常基线值所有落在右侧的消息量就是优化空间。把这张图放到 PPT 里短信业务流程的结论就落到了一个可量化、可追踪的坐标上。本文还有配套的精品资源点击获取
返回列表