2019独角兽企业重金招聘Python工程师标准>>>

最近上线了一个推送系统。推送系统作用是将短信,邮件,app push等消息触达到用户。目前功能上只实现了短信通道,并且随着业务量的扩大,还需要并行扩展推送能力。

公司的对推送系统的应用场景有两个,一个是主动发送,即在某一个时间点集中推送几万条短信。另一个是用户触发,通过上游系统接收到用户的行为而发送一条短信给用户。产品部门要求每条短信发送出去后,都要具体的执行报告:用户是否收到,收到的时间,失败的原因等等。所以系统就需要跟踪一次推出去的每条短信的发送状态。

目前系统接入了5个不同的短信网关。这个5个短信网关其中有4个是通过提供开发包(jar包形式),以socket的方式连接,一个是通过http协议访问,所以对于短信状态的处理也就有两种不同的形式。

第一种socket形式。这种开发包的处理方式一般是在第一次发送时与网关建立socket链接,双方在链接中进行通信。有的开发包里会自动维护该链接的状态,保证不会断掉,一直可以工作。而有的开发包则没有该项功能,需要客户端去维持这个链接。

如果系统中没有短信上行的需求,可以不做维持,在发送的时候判断一下链接是否可用,如果断掉,重新建立就是了。如果有上行的需求,恰巧连接断掉,那就会收不到网关推送过来的上行信息了,这种情况下必须维持。维持的方式一般都是定时去检查链接是否可用,如果不可用,立刻建立恢复。我们在接某个网关的时候,发现这个链接维持2个小时一般没有问题,如果单纯检查链接,调用方法返回是通的,但实际上已经不可用了,判断不是很准确,所以我们干脆不再去检查这个链接,而是每个一小时发一条短信,用正式的短信发送去维护他,这样比较省事。这里面还有一个小插曲,每小时发送的短信,开始时接收方设置成了10086,后来被网关方发现,说每小时给10086这样的号码发一条不大好,后来又设置成了公司内部的一个测试号码。

一般jar包中封装好了短信发送接口,短信报告回调接口,短信上行接口。要想追踪每条短信的发送状态,必须对回调接口的数据进行处理。

已其中一个短信网关的开发包为例。它的整个一条短信发送过程分成了3个处理部分:

一,发送。发送时会得到一个seqId,这个是在客户端标示短信的id

二,第一次回调,网关返回seqId和msgId 两个值。这次回调标志着短信已经进入网关的发送队列里,排队等待发送,msgId是在网关端唯一标示该短信的id

三,第二次回调,网关返回msgId和status,errMessage三个值,标志着该条短信最终的状态,用户是否收到出错原因等。

通过上面三个步骤可以看到,必须每次都要进行关联处理,才能保证最后的短信状态。

步骤

seqId

msgId

status

我们的具体流程是:以一次发送10w条短信为例

一,10w端短信由其他系统插入到数据库中,作为一个发送task通知推送系统,每条短信都有一个自增长的smsId。

二,推送系统批量取出10w条短信,调用短信网关,每条短信都得到一个seqId。这样每条短信都需要根据smsId,更新seqId

三,第一次回调,每条短信要根据seqId,更新msgId

三,第二次回调,每条短信要根据msgId,更新最终的状态。

这样算起来10w条短信,最终发送完毕要更新30w次数据,而且这其中有两个要注意的是:1, 三个步骤必须按照顺序执行,否则where语句中需要的条件,数据库里根本还没有插入。2, 10w条瞬间发送,大量的写和回调在短时间内就要操作,要保证不会丢失。

针对这个情况我们采用队列的方式来处理,利用RabbitMQ来缓存所有的数据库操作。RabbitMQ即可以缓存大量的对象不会丢失,而且先进先出,保证了这三步执行的顺序。队列中缓存的对象封装成SmsDto这样一个类,除了必要的字段后,另外增加了一个sqlAction字段,在对象从队列中pop出来后,判断是进行第几步的数据库操作。

public static final int UPDATE_SEQID_STATE_BY_SMSID = 100;public static final int UPDATE_MSGID_BY_SEQID = 101;public static final int UPDATE_STATE_BY_MSGID = 102;

这样在发送快速执行的时候,不用担心数据库短时间内的大量写,可以通过队列pop的速度来控制写的速度。

其中系统优化的一个地方是队列pop写,开始的时候是每pop一个smsDto,根据sqlAction就执行一次数据库的操作,这样发现写的速度太慢,产品要求客户可以实时在网页上看到发送的统计结果,而我们的发送回调经常要写2,3个小时才能从队列里消费完。针对这个情况,就是要批量写数据库,然而又必须严格按照顺序来执行,所以就做了个3个List,根据sqlAction分别将smsDto放入这个三个不同的list里,在一分钟的间隔里,按照顺序来批量保存在3个List。这样保存的效率大大提高,基本上每条短信都可以实时从网页上看到发送状态。

/*** 批量处理数据库操作* 必须按照顺序执行* */private void batchSave(){if (!step1List.isEmpty()){smsService.save(step1List);}if (!step2List.isEmpty()){smsService.save(step2List);}if (!step3List.isEmpty()){smsService.save(step3List);}  step1List.clear();step2List.clear();step3List.clear();}

以上是socket方式发送短信的处理方式。http协议的方式一般是通过在网关设置一个自己系统的回调地址来接收发送报告和短信上行的。这就需要在自己系统实现两个接口来接收返回的信息。

http形式一般在url上可以批多个手机号来发送,类似于http://ip:port/send?content=abc&mobile=m1,m2,m3..我们使用的网关会在这个请求后返回一个唯一的码,类似于上述的msgId,唯一标示这一批短信的一个id。

在自己系统实现的短信状态回调接口类似于http://ip:port/report?msgId,mobile1,status,time;msgId,mobile2,status,time...这样就可以根据msgId和mobile来唯一确定数据库中的一条短信记录,来更新发送状态了。

短信网关的调用已经属于古老的成熟的技术了,大体情况也基本相同,一个成熟的网关都可以得到每条短信的发送结果,这些都从他提供的开发包,文档里来确定具体的实现方式。不同的可能就是各自在对大量状态更新方面的处理方式,这就需要结合各自的业务需要来实现了。

转载于:https://my.oschina.net/kill3bb/blog/158437

java发送短信的发送报告处理相关推荐

  1. 移动发送短信的状态报告

    移动发送短信的状态报告  ISMG向SP送交状态报告中的STAT字段含义:发送短信的应答结果.SP根据该字段确定CMPP_SUBMIT消息的处理状态. 错误对照  CB:0001 非神州行预付费用户  ...

  2. java实现短信验证码发送(架子是springboot 服务平台选择腾讯云短信服务)

    业务需求:公司扩展新业务,新增短信验证码提醒服务,负责功能模块完善 暂时只研究了腾讯短信服务的发送(看api谁都能copy出来),短信状态回执(也挺简单,只是自己想复杂了),短信回复回执(暂时没弄明白 ...

  3. java 手机短信_JAVA发送手机短信

    JAVA发送手机短信,流传有几种方法:(1)使用webservice接口发送手机短信,这个可以使用sina提供的webservice进行发送,但是需要进行注册;(2)使用短信mao的方式进行短信的发送 ...

  4. java实现短信验证码发送(基于阿里云短信sdk)

    随着互联网的兴起,各行各业的需求都在不断的增加.随着业务的扩大,企业给用户发送短信验证码的业务,也是如火如荼.在这里,calvin给各位开发者推荐阿里云短信平台.原因有二:1.接入较简单,开发成本低 ...

  5. php发送短信发送失败如何处理,php – 从我的网站发送短信(仅发送不接收)

    答案1:这是一个非常好的短信API: http://www.clockworksms.com/ 答案2: 这不是一个API解决方案,而是一个概述如何使用PHP5轻松构建自己的解决方案的概述.要将短信发 ...

  6. php定时发送短信,php发送短信代码

    /*-------------------------------- 功能:  HTTP接口 发送短信 修改日期: 2011-03-04 说明:  http://api.sms.cn/mt/?uid= ...

  7. 阿里云服务 - Java实现短信验证码发送 --(完整教程)

    我们在实现登录注册的时候,常常用到了短信验证码校验,下面给大家简单介绍阿里云的短信服务平台. 相关jar包: aliyun-java-sdk-core-3.2.2.jar(点此下载) aliyun-j ...

  8. twilio php 发送短信,Twilio发送短信

    简介 Twilio 为将来的商业沟通提供强大支持,并使开发人员能够将语音.VoIP 和消息传送嵌入到应用程序中. 它们对基于云的全球环境中所需的所有基础结构进行虚拟化,并通过 Twilio 通信 AP ...

  9. Java用户注册服务器发送短信验证码功能实现

    <–start–> 当客户端发送了http的请求给服务器之后,服务器获取手机号然后调用短信平台给该手机号发送短信验证码. 给服务器发送请求的js代码: <script type=&q ...

最新文章

  1. 学习使用React和Electron一次构建自己的桌面聊天应用程序
  2. HDLBits 系列(35)Lemmings Game
  3. 动手完善个性化弹出提示框的过程及乐趣
  4. 一行代码搞定 Scrapy 随机 User-Agent 设置
  5. C++ Primer (二)目录
  6. 前端学习(2523):展示博客并添加方法
  7. Docker 私有仓库registry
  8. 女方父母总是插手家里的事怎么办?
  9. 地面指示标志_消防应急照明和疏散指示标志设置要求,图文详解
  10. VS2010中如何查看DLL的导出接口
  11. 解决linux 运行自动化脚本浏览器无法启动问题
  12. python3安装MySQLdb
  13. Unity 3D中的内存管理
  14. 吃鸡手游服务器响应超时闪退,吃鸡界面怎么老是连接超时 | 手游网游页游攻略大全...
  15. c++ ‘-DNODE_GYP_MODULE_NAME=libsass‘ ‘-DUSING_UV_SHARED=1‘ ‘-DUSING_V8_SHARED=1‘ ‘-DV8_DEPRECATION_
  16. 计算机绘图软件应用于哪些领域,解答电脑绘图软件有哪些
  17. 画中画 视频叠加 视频覆盖 overlay
  18. 公司申请微信订阅号需要的材料及注意事项
  19. Mysql 编程实战三之计算两个日期的工作日数
  20. eclipse 反应慢优化

热门文章

  1. 高通发布《5G经济》研究:将催生12万亿美元市场
  2. listPageData传jsp隐藏域,在传回java
  3. K linux 部署手机 centos6.5
  4. Nginx Upload Module 上传模块
  5. 正式开通我的开源博客
  6. UltraEdit 所有快捷键 说明
  7. 校园网双出口配置实例
  8. 巧用ASP.NET预编译Web应用程序规避调用延迟,徐汇区网站设计
  9. VS2012编译文件报错——error LNK2001: 无法解析的外部符号 __imp___CrtDbgReportW
  10. 任务调度、磁盘、进程管理、PRM和YUM