ARTICLE DETAIL

资讯详情

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

企信通短信平台部署实战:源码架构、CMPP协议与故障排查

企信通短信平台部署实战:源码架构、CMPP协议与故障排查 简介这是一套面向企业短信服务场景的「企业信使企信通短信平台」完整Web工程适合需要部署、学习或二次开发企业短信系统的开发者也适合准备搭建企业短信中台的技术团队。包内包含ASP.NET网站服务、后台管理页面、SQL Server数据库文件及前端资源覆盖通知发送、订单提醒、验证码、客户关系管理等典型业务并支持定时、批量、触发式发送等策略。压缩包共2447个文件大小约26.72MB其中dll、aspx构成程序主体mdf/ldf保存业务数据js/css/gif等完成界面呈现compiled文件保留编译中间信息整体结构便于定位。内容预览可见asmx服务接口与多个后台操作页面有助于理解短信网关、任务调度、用户和联系人管理之间的调用关系。资源已有363人浏览学习具备可运行的企业短信平台雏形可作为二次开发、接口对接和架构扩展的参考蓝本。1. 企业信使企信通短信平台拿到的 zip 里到底装了一套什么系统当你看收藏夹里的这条下载记录时别以为「企业信使企信通短信平台.zip」只是一个能发短信的网站源码。它真正的身份是一套包含短信网关、发送服务和后台管理的完整工程圈内通常叫它 SMS 企业信使。这套东西能解决的核心问题只有一个把业务系统产生的短信通过数据库队列和运营商网关送到用户手机并且拿到投递回执。它适合两类人一类是做课程设计或毕业设计、需要交付一个完整短信系统的学生另一类是要在公司内网私有化部署短信通道的开发和运维。但要让它真正跑起来你得先过三道关环境、数据库、通道参数。2. 先搞懂企信通短信平台的三层结构网关、队列和后台分别解决什么问题2.1 从 zip 包结构反推工程归属源码工程、数据库脚本和配置文件的分布规律大多数以“企业信使”或“企信通”命名的压缩包解压出来的结构是有规律可循的因为这类源码通常来自毕业设计或早期商业源码的二次分发。我在拿到一个陌生 zip 之后不会先去打开里面的说明文档而是直接看文件分布。这里有几个典型特征。第一zip 根目录下大概率会有 .sln 或与 .sln 同级的解决方案文件夹。.sln 的存在意味着可以用 Visual Studio 一次性打开整个工程这个后缀如果没看错基本上能确认它是 .NET 系项目而不是 Java 或 PHP。更老一点的版本可能是 .dsw/.dsp那属于 .NET 诞生之前的 VC 时代遇到这种不建议继续投入时间因为短信协议和页面技术都过于老化改造成本比新写一套还高。第二源码包里会有一个或多个 .sql 脚本。脚本的命名和数量可以说明平台的完整度只有一个整合脚本的包通常是作者把建库、建表、初始化数据写在一份文件里如果拆成了多个脚本往往对应多张业务表例如发送表、通道表、用户表。这个时候不要急着执行先看脚本头部注释有没有写 SQL Server 版本要求。多数老包写的是 SQL Server 2000/2005在新实例上执行时大概率要改兼容级别。第三配置文件。老工程里最容易被忽略的是 .config 文件不止 web.config 一个还有可能藏在类库里名称为 App.config。当你在 web.config 里改了连接字符串却发现系统仍然连旧库时十有八九是另一个工程目录里的 App.config 在捣乱。我一般会用 PowerShell 把整个目录里的 config 文件找出来逐个搜索连接字符串关键字Get-ChildItem -Recurse -Include *.config | Select-String -Pattern Server|Data Source这行命令会把所有配置文件里出现的数据库连接地址一次列出来看它们是否统一。如果同一个数据库名在多个文件里出现那么部署时要全部改只改一处会出现“后台能登录发送服务连不上库”的诡异现象。还有一个容易被忽略的判断点是 packages 文件夹和 bin 目录。如果 bin 里已经有一堆编译好的 DLL说明作者给的是“可运行包 部分源码”的混合体这时候可以先尝试直接跑编译产物节省时间如果你需要改协议逻辑再回头编译源码。判断哪些 DLL 是系统自带、哪些是第三方引用可以在 Visual Studio 的“引用”里看凡是带 Cmpp、Sgip、Smgp 字样的都是这个平台自己的核心库出了问题只能靠源码调。2.2 短信平台在电信侧走的是哪条路CMPP、SGIP、SMGP 三网协议企信通这个名词最早出现在 2007 到 2010 年之间的产品里当时企业短信通道的接入方式并不像现在有那么多 HTTP 云接口绝大多数走的是运营商规定的 TCP 长连接协议。如果你看源码里的通信层会发现核心类都在处理三件事连接、提交和状态报告。对应移动侧协议叫 CMPP联通侧叫 SGIP电信侧叫 SMGP。这三套协议报文结构不完全一样但设计思想相同客户端与网关维持一条长连接定时发送心跳保活要发短信时封装一个 submit 报文短信到达后网关异步返回一个 report 报文。很多人第一次接触 CMPP 会把它当成一个黑匣子实际上你只需要看懂报文里最要紧的四个字段消息来源编号、目的号码、消息内容编码、业务代码。这四个字段在配置里出问题是短信平台搭好后发不出去的最常见原因。例如 CMPP 3.0 协议里消息内容长度字段的单位是字节而不是字符一条 70 个汉字的中文短信使用 UCS2 编码后长度变成 140 字节如果源码里把这个长度按字符数填网关会直接拒绝返回状态码表明“消息长度错误”。我在带新手排查时经常让他们先看这个长度换算比查代码逻辑快得多。协议层还涉及一个容易踩的细节用户名密码。CMPP 连接报文里的密码不是明文而是经过 MD5 处理后的密文企信通老代码里具体用 MD5 一次还是两次、加不加盐取决于作者实现的版本而这一规则必须和你接入的短信服务商一致。你从 A 服务商申请的参数放到 B 服务商的测试网关里往往返回“认证失败”。因此拿到源码后第一步不要改协议层代码先用服务商配的测试参数把 CMPP_CONNECT 跑通再考虑定制。2.3 为什么这类工程偏爱 .NET SQL Server定时扫描表和存储过程的职责划分把这套系统的运行机制展开你会发现它本质上是一个“数据库驱动的定时任务”模型。Web 后台负责把短信请求写入发送表定时器或 Windows 服务每隔几秒扫描这张表的新增记录封装后发给网关。这个模型在现在看有点笨但在 .NET Framework 4.0 时代是中小型短信平台的通用做法。选择 SQL Server 的另一个原因是存储过程可以在数据库内完成批量取数和状态更新发送服务只要调用存储过程即可不需要让业务逻辑散布在多个项目里。实际工程里发送服务通常会调用这样一个存储过程CREATE PROCEDURE [dbo].[sp_GetPendingSms] TopCount INT 100 AS BEGIN SET NOCOUNT ON; UPDATE TOP (TopCount) t SET t.Status 1, t.SendTime GETDATE() OUTPUT inserted.* FROM dbo.tb_sms_send AS t WHERE t.Status 0; END这段存储过程的逻辑是从待发送表里取出指定数量待发送的短信把它们状态改成 1 并在同一个事务里输出记录避免多个发送线程取到同一条数据。TopCount 参数控制一次取多少条老包默认一般是 100如果通道速度快可以调高到 500但调太高容易让数据库锁竞争加重这个度要结合发送量来看。存储过程还有一个好处重试机制可以放在数据库层。比如发送失败返回状态码后在表里把状态改回 0 并累加重试次数等待下一次扫描再次送出整个过程不需要改 C# 代码。2.4 数据表最少要有哪几张发送表、状态报告表和通道配置表一个交付方案能否直接用于生产看表结构就一目了然。企信通类平台的数据库里最少要出现四类表管理用户表、短信发送表、状态报告表、通道配置表。在一个正常的老包里这些表往往以 tb 或 sms_ 开头字段命名有明显特色。发送表字段通常至少包含id、mobile、content、sign、channel_id、status、retry_count、send_time、submit_time。其中 status 是关键0 表示待发送1 表示已提交待回执2 表示成功9 表示失败。channel_id 对应通道配置表的主键。状态报告表则记录网关异步回传的原始信息至少要有 msg_id、mobile、status、report_time 这几个字段。status 字段里出现的 DELIVRD 表示成功投递EXPIRED 表示短信过期UNDELIV 表示未送达不同服务商的英文缩写略有差异但看到 DELIVRD 就基本可以确认链路是通的。通道配置表保存的是接入服务商所需的参数包括网关 IP、端口、SP 编号、登录账号和密码。很多老包在初始化脚本里写死了一组测试网关地址而测试网关早就失效了。如果你发现通道表里只有一条记录并且状态栏写着“已停用”那多半是作者留下的测试通道真正要用的参数需要你在后台重新添加。判断平台完整度的另一个参考是看有没有签名表和模板表。如果只有发送表和后台页面没有签名表说明这套源码的发送流程不完整依赖发送时手动拼签名这在正式通道上很容易被拒。反过来只要有完整的四张表业务系统接入时就只需要往发送表里插行风险小得多。3. 把 zip 变成能跑的本地短信网关解压、建库和启动的最小操作路径3.1 解压和目录检查bin、web.config、sql 脚本各对应什么拿到 zip 的第一步先不要用系统自带的“全部提取”直接在资源管理器里解压到指定目录。目录位置选 D:\SmsProject 这种纯英文路径。用中文路径会在两步出问题一是在 IIS 里配置站点时物理路径里的中文可能被转义成乱码二是有些老代码里用相对路径计算今天日期和日志目录中文路径会导致文件创建失败。解压完成后打开目录第一梯队看三类文件.sln、web.config、.sql。第二梯队看有没有 WinService 项目或 Console 项目这个决定了系统由几个进程协作。我习惯在 PowerShell 里做一次比较完整的侦测一是看解决方案里的项目结构二是看配置文件里是否包含短信网关字样Get-ChildItem -Recurse -Include *.csproj,*.sln,*.sql,*.config | Select-Object FullName, Length这段命令输出的清单能帮你快速判断这个 zip 是纯源码还是带可运行产物。如果发行版里根本没有 .csproj 只有一堆编译好的 DLL那多半是当年从服务器上直接打包的成品部署方式会稍有不同需要把 DLL、aspx 文件、bin 目录一起放到 IIS 站点下运行。如果是源码头还要关注项目引用的 NuGet 包是否齐全。老包最常见的翻车点是用 Visual Studio 打开后一堆引用变黄原因是当时引用的第三方 DLL 没有包含在 zip 里。这种情况下先把所有项目“引用”里标记为感叹号的项删掉改成从本地 bin 里重新添加。打开 Web 工程下的 web.config把连接字符串这一段拿出来看。大部分包的格式是connectionStrings add nameSmsConn connectionStringServer.;DatabaseSMSPlatform;Uidsa;Pwd123456; providerNameSystem.Data.SqlClient / /connectionStrings这里 DatabaseSMSPlatform 要和实际建的库名一致中间不要有多余空格。如果把 password 字段设置成了加密后的密文后面改密码就不能直接改这个字符串需要在源码里找加解密函数在后台页面里重新保存一次配置。3.2 SQL Server 建库建表执行脚本和附加数据库两种方式的取舍建库是整个部署里最需要耐心的环节。老包提供的数据库脚本有两种形态完整脚本和备份文件。完整脚本通常以 USE database 开头执行后自动建库备份文件则是 .bak需要在 SSMS 里“还原数据库”。我这里建议一个原则能跑脚本就跑脚本尽量不要去附加 .mdf/.ldf。原因有几层附加对文件路径和权限敏感容易出现文件权限错误附加后数据库登录用户会和原实例绑定出现孤立用户后续还得调用存储过程修复登录关联。采用脚本方式时多数老包在脚本头部会有一段 CREATE DATABASE 语句。如果你的 SQL Server 是 2008 R2 之后的版本并且脚本里写的是类似 “CREATE DATABASE SMSDB ON PRIMARY (NAMESMSDB, FILENAMED:\SMSDB.mdf)” 这样的路径要把路径改到当前实例的数据目录否则执行直接报错找不到路径。为了避免这个问题最简单的做法是先在 SSMS 里建一个空库并记下库名再执行脚本时把 USE [master] 改成 USE [SMSDB]然后仅执行建表部分。用命令行方式操作更可控sqlcmd -S . -U sa -P 123456 -d SMSDB -i sms_tables.sql参数说明-S 指定 SQL Server 实例名本机默认实例用一个小数点-U 和 -P 是登录用户名和密码-d 指定目标数据库-i 指向要执行的脚本文件。执行过程中如果看到报错信息里出现“对象名无效”大多是脚本里表之间有依赖执行顺序的问题不要把整份脚本一次性跑完按 CREATE TABLE 的顺序分段执行每次停一下观察结果。脚本跑完后的验证语句是SELECT name, type_desc FROM sys.tables WHERE name IN (tb_sms_send,tb_sms_report,tb_sms_channel);三条记录都在说明表结构没问题。如果只有前两张表没有通道表说明这个包把通道参数写死在配置文件里那后面对接通道时要改的是 .config 而不是数据库。3.3 启动 Web 管理后台IIS 与 Visual Studio 自带的两种跑法数据库就绪后进入源码编译环节。用 Visual Studio 打开 .sln右键解决方案选择生成看输出窗口有没有错误。老包最常见的生成错误是缺少 System.Web.Extensions 或 AjaxControlToolkit 等组件引用这些通常可以在项目的 packages 文件夹里找到如果没有就去 NuGet 重新安装对应版本。编译通过后启动方式有两个选择。方式一用 VS 自带的 IIS Express 直接跑。启动前把 Web 项目设为启动项目按 F5 后浏览器访问 localhost:端口号。这个方法适合开发调试缺点是一旦关闭 VS 服务就停不能作为长期运行的部署方式。方式二用 IIS 部署到本机。在 IIS 管理器里新建网站物理路径指向 Web 项目的根目录应用程序池选择 .NET v4.0 经典模式。老企信通页面大多基于 WebForms在集成模式下容易出现“处理程序映射与集成管道不兼容”的错误把应用池改成经典模式是这类问题的保底办法。启动后如果直接报数据库连接错误别急着怀疑代码。先检查 SQL Server 是否允许本机连接、TCP/IP 协议是否启用这两项是新手最容易忽略的。TCP/IP 协议启用步骤打开 SQL Server 配置管理器展开 SQL Server 网络配置找到实例名对应的协议右键启用 TCP/IP然后重启 SQL Server 服务。改完之后再用连接字符串能连上数据库后台登录页才能正常访问。3.4 发送服务进程为什么不随 Web 启动很多人在后台里看到短信列表就觉得系统部署完了结果一发送短信就发现发送记录永远停留在待发送状态。这个现象背后的原因是你只启动了 Web 后台没启动发送服务。企信通类源码里发送服务通常独立为一个 Windows 服务项目或控制台程序。它的任务是定时扫描发送表并连接网关和 Web 项目是两个进程。我在部署时一般会先把服务项目编译出来的 exe 直接双击跑一次观察控制台日志确认它能正常连接数据库和网关。确认无误后再注册为 Windows 服务sc create SmsSendWorker binPath D:\SmsProject\SendWorker\SendWorker.exe start auto这条命令里最容易错的地方binPath 后面空格不能省略start auto 同理等号右边留一个空格再用值。如果服务创建后无法启动去“事件查看器”里看系统日志日志里通常写着登录账号权限不足。给服务指定一个本地系统账户能规避掉多数权限问题。服务启动后还要确认它不是启动即退出。发送服务是长循环控制台窗口不应在十几秒内自动关闭如果自动关闭了在代码里找 try-catch 或全局异常日志把异常写出来再排查不要盲目重启服务。4. 真正把短信发出去通道参数、签名模板和一条测试短信的完整链路4.1 通道接入参数对照表网关地址、端口、企业代码和 SP 账号平台本身只是壳通道参数才是灵魂。我处理过的老企信通包里几乎每个包的通道配置页都长得很像但参数坑位不统一。有些把“企业代码”和“SP 账号”分开填有些合在一起接入的时候如果不知道这两个字段的区别很容易填反导致登录网关失败。现在的短信服务商能提供 CMPP 网关参数的已经不多了不少给的是 SMS 云内置接口也就是一个 HTTP 调用地址配上签名模板就能发配置方式完全不同下面按老包最常见的 CMPP 网关来梳理。企业代码是接入企业在一家服务商侧的唯一编号SP 账号则是具体业务使用的登录名两者并不总是同一位数。服务商给你的开通文档里会专门标注哪个字段填到哪里。企信通后台的通道管理页通常要求填以下核心参数参数示例说明网关地址211.136.53.18CMPP/SGIP 网关服务器地址网关端口7890CMPP 默认端口联通 SGIP 常用 8801企业代码900168服务商分配的企业编号SP 账号900168001业务账号登录网关用密码自定义字符串部分服务商要求 MD5 后传输业务代码10086运营商侧业务标识填完参数保存后不要急着发短信先确认到网关的 TCP 连接能通。Windows 自带的 PowerShell 就能测Test-NetConnection -ComputerName 211.136.53.18 -Port 7890返回 TcpTestSucceeded 为 True 说明网络层通。这一步能把“网络不通”和“协议登录不上”分开。很多云服务器默认安全组里没放行到运营商网关的出口端口导致平台显示连接超时实际是防火墙把出方向拦截了测试网络连接时重点看的正是这个。4.2 配置签名和模板为什么内容里不能裸奔老平台的“签名管理”和“模板管理”是很多用户不看的页面但这两个功能直接决定正式通道能不能发出去。企信通平台里签名通常以【xxx】的形式插在短信内容最前面比如【企业信使】您的验证码是 123456。在运营商侧审核时签名必须是已备案的企业名称或产品名称没有备案的签名会被网关以“非法签名”的原因拒绝。源码里一般会提供一个“签名审核”功能帮你提交备案但实际审核是在服务商侧完成的等审核通过才能在通道里正常使用。模板的作用是限制发送内容格式。主流的行业短信通道要求内容里除了变量之外其它文字必须固定。比如模板“您的订单${1}已发货请注意查收”发送时把 ${1} 替换为订单号。老平台发短信时如果不走模板而是一整段自由输入正式网关往往返回“内容包含非法关键字”或直接拒绝。所以在配置完后先建一个最简单的“您好您的验证码是${1}有效期5分钟请勿泄露。”模板再把变量替换成真实内容这样链路排错时比较干净。4.3 调用发送接口用 C# 写一个最小 HTTP 调用示例配置完通道接下来要验证业务系统能不能把短信送进平台。老企信通包通常对外暴露一个 aspx 页面作为 HTTP 接口地址形如 /api/sms_send.aspx接收 mobile 和 content 参数。也有部分版本不提供 HTTP 接口而是直接建议业务系统往发送表插记录后者依赖数据库账号权限不太适合跨系统集成。下面是给业务系统一个最小 HTTP 调用假设平台接口接收 POST 参数并返回字符串using System.Net.Http; using System.Threading.Tasks; using System.Collections.Generic; public class SmsClient { private static readonly HttpClient _http new HttpClient(); private readonly string _apiUrl; public SmsClient(string apiUrl) { _apiUrl apiUrl; } public async Taskstring SendAsync(string mobile, string content) { var form new Dictionarystring, string { { mobile, mobile }, { content, content } }; var response await _http.PostAsync(_apiUrl, new FormUrlEncodedContent(form)); return await response.Content.ReadAsStringAsync(); } }逻辑说明FormUrlEncodedContent 会自动把中文内容做 URL 编码不需要手动转码mobile 参数只允许数字可以提前用正则做校验。接口返回的字符串如果是 0 或 success说明平台已经收下短信并把内容写入发送表。这种情况不代表手机已经收到只能代表进入待发队列只有状态报告表里出现 DELIVRD 才算真正成功。另外要注意一点老平台接口对短信长度有限制超过 70 个汉字可能直接返回错误调用方应在入参时按 70 字拆条而不是把长文塞给平台。4.4 从后台手动测试一条短信的完整生命周期接口调通后再回到后台手动发送一次把它当成全链路验收。我习惯在后台“短信发送”页面填上自己的手机号手动触发一次普通发送然后立刻去 SQL Server 里看发送表的状态SELECT TOP 5 Id, Mobile, Content, Status, CreateTime, SubmitTime FROM dbo.tb_sms_send ORDER BY Id DESC;执行这条查询后能看到最新一条记录。状态从 0 变成 1说明发送服务已经取走了这条消息状态变成 2 或 9说明已经拿到回执其中 2 代表成功。如果记录停留在 0先回到发送服务日志确认发送服务在运行如果服务在运行但记录始终是 0看服务连接数据库的账号是否有 update 权限。状态为 1 后再查报告表SELECT TOP 5 MsgId, Mobile, Status, ReportTime FROM dbo.tb_sms_report ORDER BY ReportTime DESC;报告表出现 DELIVRD表示短信已经由运营商下发给客户机。这个完整链路插入 → 取走 → 提交 → 回执每一步都有对应表和日志按这个顺序排查比看代码要高效得多。5. 企信通短信平台部署避坑手册数据库连不上、短信发不出、状态报告不到5.1 解压后 IIS 启动报 500.19web.config 的权限问题现象把整个 zip 解压到 D 盘后在 IIS 里新加网站指向 Web 根目录访问显示 HTTP Error 500.19提示无法读取配置文件。原因IIS 进程池的账户对解压目录没有访问权限。zip 包里的文件从其它机器带过来NTFS 权限列表里缺少 IIS_IUSRS 组于是 IIS 读取不到 web.config。解决右键 Web 根目录 → 属性 → 安全 → 编辑 → 添加 IIS_IUSRS给读取和执行权限。如果项目用的是应用程序池自定义账户还需要给该账户加上权限。这是我在帮客户部署老源码时碰到概率最高的一条跟代码无关但往往被人排查很久才想到是权限。5.2 数据库脚本执行成功后没有表脚本开头带了 USE 和 GO 的坑现象在 SSMS 里成功执行整份 .sql 脚本没有任何报错但是在数据库列表里看不到新建的库或者在指定库下看不到新表。原因脚本开头有 CREATE DATABASE 和 USE 语句SSMS 执行时把当前连接切到了新库但你随后查看的是自己手动创建的那个库还有另一种情况是脚本文件编码是 UTF-8SSMS 按 ANSI 读取导致中文注释乱码把整个脚本截断执行了一部分看起来成功实际后面语句没有跑。解决先用文本编辑器查看脚本前 20 行找到 USE [库名]确认脚本要创建的库名是否与你预期一致。执行之前把 SSMS 的当前库选择为 master再整段执行或者干脆用第 3 章里的 sqlcmd 方式用 -d master 参数执行脚本里的 USE 语句会自动把上下文切到目标库。执行完成后再用 sys.tables 查询确认表数量以查询结果为准不要看 SSMS 的“消息”窗口。5.3 短信提交成功但手机收不到回执状态码和通道配置双查现象后台界面提示发送成功发送表状态从 0 变成 1但过了很久手机没有收到短信报告表里也没有记录。原因这一类问题八成出在通道配置未真正生效其余出在消息编码。最常见的是配置文件里的网关地址还指向某测试环境而测试环境早已不通或者是消息超过 70 字被网关拒绝但错误没被正确记录。解决先查看报告表有没有网关返回的状态码。没有报告记录说明报文没有到达网关或连接没有建立成功回到 4.1 的 Test-NetConnection 验证到网关地址的连通性再检查发送服务本机端口出站防火墙规则。如果报告表里有状态码对照服务商返回码表查看具体含义常见的“9”表示未定义错误“12”表示伪造 IP 或无效源地址。密码错误在 CMPP 里比较隐蔽因为发送的密码是经过加密处理后的密文必须确认网关侧的加密规则和代码一致。调试到这一步时把发送服务日志级别调到 Debug重新触发一次发送日志里会打出 CMPP_CONNECT 的返回码直接定位是连接层还是业务层的问题。5.4 后台中文乱码从数据库到页面的编码不一致现象后台列表页中文显示成问号或者类似“浣犲ソ”的乱码数据库里字段内容也是同样乱码。原因老源码页面编码是 GB2312而数据库排序规则或连接字符集是 UTF-8如果是通过 HTTP 接口提交中文还可能因为接口页面编码和数据库连接编码不一致在入库时转换错误。这个属于典型的环境兼容问题不是单纯改页面 meta 标签能解决的。解决分两步处理。第一步把 web.config 中显式声明全局编码globalization requestEncodinggb2312 responseEncodinggb2312 culturezh-CN /改完重启 IIS 后新写入的中文应该正常。如果数据库里已有的乱码数据想恢复需要在写入时编码没坏之前就修复乱码一旦入库字符集已经丢失只能靠更新数据或重新发送没有“后悔药”。5.5 发送服务跑几个小时就卡住连接资源未释放和线程卡死现象发送服务刚启动时一切正常跑了几小时后发送记录开始堆积服务进程还在但是日志不再更新。原因这是老 .NET 平台的经典难题。发送服务里建立的 TCP 长连接或数据库连接没有正确释放运行几小时后连接池耗尽或者轮询逻辑里某条异常数据导致循环卡死服务表面在运行实则线程已经停摆。解决先在任务管理器确认进程 CPU 占用如果 CPU 占用为 0 而日志时间戳长时间不更新基本可判定为卡死重启服务只能临时解决。正确做法是给服务的外层循环加一个看门狗最简单的是在 SQL Server 作业里写一个监控脚本每 5 分钟检查一次发送服务心跳表的时间戳超过 10 分钟没更新就重启服务。心跳实现也简单服务循环里每轮更新一次心跳表的 last_time 字段。这类问题发生在生产环境时重试多少次都没有意义关键是先让监控把问题兜住再逐步分析具体的连接泄漏代码。6. 从能发到可靠发回执状态机、失败重试和业务系统接入的进阶落法6.1 用状态机约束发送流程能发通只是起点长期跑不出问题靠的是状态管理。我一般会把发送表的状态扩展成一套显式状态机0 待发送、1 已提交待回执、2 成功、8 超时无回执、9 失败。在每次状态变化时写一条日志到独立日志表后面复盘时能看清每一条短信走了哪几步丢在哪一环。6.2 重试策略别做成死循环针对 9 失败回执可以做重试但每次重试要递增时间间隔并且限制总次数我常用的策略是总数 3 次、间隔 5 分钟。针对 8 超时无回执网络上短信可能已经下发重试会让用户重复接收这类几乎不重试。重试逻辑要写在服务里而不是人工操作否则凌晨出现大批失败时没人盯着处理。6.3 给源码加一个通用 HTTP 接口最后一步把平台能力封成一个通用 HTTP 接口供公司内部系统统一调用。我会加一个一般处理程序接收几个固定参数账号、密码、手机号、内容、签名、定时时间。校验账号密码后直接插发送表返回本次消息 id。这样业务系统与短信平台解耦后续换通道、换服务商只需要改平台配置业务系统一行都不用动。跑这套平台最大的教训是老 zip 里的源码不是拿来即用的产品更像一个带病运行的旧系统部署过程本质上是在给它修环境兼容问题。很多人栽跟头不是栽在代码上而是栽在“数据库库名没对上”“IIS 权限没给”“发送服务忘了启动”这些环境细节上。手头拿到这套源码时先把环境问题排干净再谈优化协议和性能链路自然就稳了。希望这篇记录能帮你在第一次跑通这条链路时少走几段弯路也让你交出去的部署不只是“页面能打开”而是“短信真的能稳定发出去”。本文还有配套的精品资源点击获取
返回列表