1. 项目背景与核心价值
这套基于C#开发的企信通源码,本质上是一个企业级短信网关中间件。我在2018年第一次接触这类系统时,发现市场上商业化的短信平台往往存在两个痛点:一是接口封闭不利于二次开发,二是按条计费的模式对中小型企业成本压力较大。而这套开源方案恰好解决了这两个核心问题。
从技术架构来看,这套代码实现了短信平台最关键的三个能力:多通道负载均衡、状态机管理和模板引擎。我实测过它的并发处理能力,在4核8G的服务器上可以稳定处理300+TPS的短信发送请求,这个性能对于大多数OA系统的消息通知场景已经完全够用。
2. 系统架构解析
2.1 通信层设计
源码采用分层架构设计,最底层的通信模块抽象得相当漂亮。通过ISMSProvider接口定义了标准化的通信契约,目前实现了三种协议适配:
- 中国移动CMPP协议(v2.0)
- 中国联通SGIP协议(v1.2)
- HTTP API通用适配器
这种设计带来的最大好处是扩展性。去年我给某物流公司实施时,他们使用的越南短信网关就是通过新增一个HTTP适配器实现的,整个过程只用了不到2个工作日。
2.2 消息队列实现
核心的异步处理模块基于RabbitMQ构建,消息流转路径设计得非常考究:
- 接收请求后立即持久化到MySQL
- 写入RabbitMQ的sms_request队列
- 消费者进程从队列获取任务
- 发送成功后更新状态到redis缓存
这种设计保证了即使在服务器宕机的情况下,最多只会丢失正在处理中的那条短信,其他待发消息都能在服务恢复后继续处理。
3. OA系统集成实战
3.1 审批通知场景
以最常见的请假审批为例,集成步骤包括:
- 在OA的审批流程引擎中配置消息触发点
- 编写C#调用代码:
var sms = new EnterpriseSMSClient(); sms.SendTemplateMessage( mobile: "13800138000", templateId: "LEAVE_APPROVED", parameters: new { Name = "张三", Date = DateTime.Now.ToString("yyyy-MM-dd"), Days = 3 } );- 在企信通后台配置消息模板:
【{Company}】亲爱的{Name},您申请的{Date}起{Days}天假期已获批3.2 性能优化技巧
在高并发场景下,我总结出几个有效优化手段:
- 连接池配置:建议将默认的20个连接提高到50-100
- 批量发送模式:使用SendBatch方法替代单条发送
- 缓存模板内容:通过Redis缓存高频使用的模板
4. FR系统对接方案
4.1 财务预警通知
对于财务系统的资金异常报警,需要特别注意:
- 设置消息优先级为最高级
- 实现失败自动重试机制
- 添加数字签名验证
配置示例:
<FRIntegration> <AlertTemplate> <![CDATA[【财务预警】账户{Account}于{Time}发生异常交易,金额:{Amount}]]> </AlertTemplate> <RetryPolicy count="3" interval="30s"/> <Security> <EnableSign>true</EnableSign> <SecretKey>YourAESKeyHere</SecretKey> </Security> </FRIntegration>4.2 对账结果推送
月末对账场景需要处理大量数据,建议:
- 采用异步回调机制
- 压缩消息内容(实测可节省40%流量)
- 使用专用高优先级通道
5. 运维监控体系
5.1 健康检查配置
在生产环境中,我通常会部署这些监控项:
- 通道存活检测(每分钟ping测试)
- 余额预警(低于1000条触发)
- 发送延迟监控(>5秒告警)
Nagios配置示例:
define service { service_description SMS_Channel1_Status check_command check_http!-H 127.0.0.1 -p 8080 -u "/health" -s "Channel1:OK" max_check_attempts 3 normal_check_interval 1 }5.2 日志分析策略
有效的日志管理方案:
- 使用Log4Net的RollingFileAppender
- 按天分割日志文件
- 关键字段索引:
- MessageID
- MobileNumber
- SendStatus
- CostTime
6. 安全防护实践
6.1 防刷单机制
我遇到过最严重的攻击是短信轰炸,现在会强制实施:
- 同号码频控(60秒内不超过1条)
- 总量限制(单IP每小时<100条)
- 验证码校验(敏感操作需二次确认)
实现代码:
var rule = new RateLimitRule { MaxRequestsPerIp = 100, TimeWindow = TimeSpan.FromHours(1), WhiteList = new List<string> { "192.168.1.100" } };6.2 数据加密方案
敏感信息必须加密处理:
- 手机号使用AES加密存储
- 日志中的内容字段脱敏
- 数据库连接字符串加密
7. 异常处理经验
7.1 通道切换策略
当主通道故障时,系统会自动切换到备用通道。但要注意:
- 不同通道的模板可能需要适配
- 签名规则可能不一致
- 运营商黑名单策略不同
我的解决方案是维护一个通道特征表:
CREATE TABLE channel_properties ( channel_id INT PRIMARY KEY, max_length INT, support_unicode BIT, signature_required BIT, template_adaptor VARCHAR(50) );7.2 典型错误代码
这些错误码需要特别关注:
- 301:余额不足
- 403:内容含敏感词
- 502:通道连接超时
- 601:号码在黑名单
处理建议:
遇到403错误时,不要简单重试,应先检查内容是否包含最新敏感词库中的词汇
8. 扩展开发指南
8.1 微信通知集成
现代办公场景往往需要多通道通知,我扩展的微信通知方案:
- 实现IWechatProvider接口
- 复用现有的模板引擎
- 统一消息状态管理
架构示意图:
[OA System] -> [Message Router] -> [SMS Gateway] \--> [Wechat Gateway]8.2 国际短信支持
对于有海外业务的企业,需要特别注意:
- 号码格式校验(各国规则不同)
- 时区处理(自动转换本地时间)
- 多语言模板(支持unicode编码)
关键代码片段:
bool IsValidInternationalNumber(string number) { var pattern = @"^\+(9[976]\d|8[987530]\d|6[987]\d|5[90]\d|42\d|3[875]\d| 2[98654321]\d|9[8543210]|8[6421]|6[6543210]|5[87654321]| 4[987654310]|3[9643210]|2[70]|7|1)\d{1,14}$"; return Regex.IsMatch(number, pattern); }这套源码最让我欣赏的是其良好的扩展性,去年为某跨境电商实施时,从接到需求到完成国际短信支持只用了3个工作日。核心就在于它清晰的接口设计和模块化的架构,这种工程规范值得很多商业软件学习。