[短彩信]C#短彩信模块开发设计(1)——架构
准备从以下几个方面简单的谈谈短彩信模块的实现:
[短彩信]C#短彩信模块开发设计(1)——架构(http://www.cnblogs.com/CopyPaster/archive/2012/12/07/2806776.html)
[短彩信]C#短彩信模块开发设计(2)——配置(http://www.cnblogs.com/CopyPaster/archive/2012/12/10/2811626.html)
[短彩信]C#短彩信模块开发设计(3)——协议(http://www.cnblogs.com/CopyPaster/archive/2012/12/12/2814918.html)
[短彩信]C#短彩信模块开发设计(4)——其他(http://www.cnblogs.com/CopyPaster/archive/2012/12/17/2821715.html)
之前写过一个彩信报文的博文(http://www.cnblogs.com/CopyPaster/archive/2012/04/28/2475240.html),其实主要的意思就是想把彩信报文贴出来给大家看看。因为根据当时我的所知,移动提供了Java版的API,但是却没有.Net版的,所以如果需要使用.Net开发彩信网关适配器服务,势必需要自行构造彩信报文,所以把一个简单的彩信报文贴出来给大家做个参考。不过我看评论,更多的大家是关注发送效率的问题。其实,从我开发短彩信的过程来看,短彩信协议本身其实只是研究和学习的一部分,其实更多的精力放在了如何在大数据量下系统交互、衔接能更快,更好,更安全上,那么这里把我对短彩信模块的一些认识谈一下,我打算从几个点来谈,以后看时间会逐篇介绍,第一篇先来谈整体架构。其实本文将的整体结构以及一些处理方法,不单适用短彩信应用,对于大数据量下,各模块交互、处理同样很适用。
先上一个张简图吧:
说明:
上层应用
上层应用指的是:所有要下行短信的子系统,当然一般对于短信而言,看业务要求是否需要处理上行(对于彩信,协议上是支持上行的,不过一般很难碰到这样的实际应用吧?我想可能只有做电视台的业务,可能会遇到彩信上行,比如用户上行一个图片彩信,然后主持人把图片显示给各位观众);
在上面的图上,直接表达的意思是,所有需要发送短彩信的模块,如果要发短彩信,只要往Amq消息队列里仍一条消息即可,不过在我某个项目中的实际应用是:在中间档了一层服务(短彩信平台),上层应用如果要发短彩信只要给短彩信平台发一条消息,短彩信会给对应的Amq消息队列发送消息。至于这个短彩信平台,我觉得一些做法和思想对于大数据量的处理和交互有帮助,这里把要点点一下,给大家参考参考。1)上层应用和短彩信平台消息通讯采用RPC方式;对外提供dll接口给上层应用直接使用(我们实际中由于下行数据量比较大,短彩信平台是一组服务,并且有增加新平台的机制(我把这种处理方式称之为分Pool,加新平台其实就是加Pool; 关于分Pool,简单来讲就是每个Pool是一组应用和数据库的集合;Pool之上有一个Global,Global中包含全局服务和数据(比如Pool划分规则)),每个平台只处理特定尾号的下行,为了隔离这种变化,所以对外提供dll接口,给上层应用直接使用,上层应用不需要关注某个下行最后会到那个短彩信平台处理);2)短彩信平台除了需要考虑如何给Amq消息队列发送消息外(后面的Amq消息队列从安全和效率上考虑,也是一组集群,所以发送/接收消息都需要额外考虑一些其他问题,这里其实也是对于上层应用隔离这种变化),本身还有一些其他逻辑(黑名单过滤;去重验证(去重很耗资源,每个平台自己维护一个B+树处理)等);
Amq消息队列集群
Amq指的是ActiveMQ,我们为什么用ActiveMQ?因为1)免费;2)MSMQ在处理跨机消息首发不方便;关于ActiveMQ的一些配置、性能调优我之前有过博文说明,如果不了解ActiveMQ的可以去参考(http://www.cnblogs.com/CopyPaster/archive/2012/04/27/2473179.html);关于对这个Amq队列集群的消息收发原则需要说明一下:
1)消息收发均采用长连接;收发方均需要自行维护一个连接池,如果收发一旦出现失败,则将该连接状态修改为不可用;自行维护的连接池需要另起线程定时检查是否有不可用连接,并尝试重连,如果连接成功,修改连接状态为可用;(注意:使用Amq消息队列,其实有一个要注意的要点:快速消费消息,避免消息大量积压。当然如果队列服务器集群多,自身内存大,这个积压阀值可逐步增大;对于Amq队列而言,Amq在短连接的情况之下其实没有任何效率可言,所以一般均使用长连接方式处理;)
2)消息发送方,每次发送消息的时候,随机选择一个可用的连接进行发送;
3)消息接收方,监听所有的连接(如果没有消息sleep一个较短时间;如果连接坏了sleep一个较长的时间);
按照上面的规则其实即能达到负载的效果,也能起到热主备的效果;
短彩信服务集群
处理方式要点:
1)每个短彩信服务需要配合一套本机MSMQ消息队列来工作;短彩信服务在收到1条Amq队列消息之后,首先将消息缓冲至本机MSMQ,这样进一步做到对于Amq的快速消费;
2)对于收到的回执/状态报告/上行信息,服务首先将消息缓冲至内存队列;(一般来讲,如果再某个应用场景下如果下行量很大,而且要求一定的发送速度,短彩信服务一般都是分省接入的,这样对于接收这些信息而言,其实是1个短彩信服务对接多个网关;当然了有些时候数据量不很大,只接一级网关的做法也有);
3)对于短彩信服务而言,一般需要考虑流控、滑动窗口(彩信协议中没有关于滑动窗口的描述,为了提高彩信发送速度,可以借鉴这个方法,另外彩信由于是http post,一般异步处理,否则流控不好控制)、连接数(短信基于socket方式,协议中通过CMPP_ACTIVE_TEST进行链路检测;彩信是无连接httpPost,此点不用考虑)
4)对于短信服务而言,如果是分身接入的,而且不是每个服务都能处理所有网关,需要考虑消息的跳转问题(在分省接入的情况下,一方面各省网关能力不同,一方面实际业务量各省也不同,或者因为连接数量不够等因素,有时候并不需要某些“小省”所有短信服务都去跑,可能会出现这样的问题);
上下行历史/回执/状态报告导入服务
一般来说如果下行量很大,那么回执/状态报告的量也很大,导入服务的职责是将消息队列中的消息,导入数据库持久;一般数据量大情况,可以采用批量导入的方式(比如接收1万条消息之后,才用BatchInsert的方式写入数据库,才实际的过程中,往往采用批量入库的方式,写入数据库花费的时间比接收这一批消息本身时间还少);