王 睿,赵 勇
(1.西安热工研究院有限公司陕西西安710054;2.长安大学信息工程学院,陕西西安710064)
随着我国经济的飞速发展,人们生活水平日益提高,手机用户的数量也不断增长,短信逐渐成为人与人之间交流的一种重要方式。短信业务一开始主要用于个人之间的信息交流,后来由于其快捷、无时空限制、价格低的优势而越来越多的被应用在企业中[1-5]。现阶段,企业短信平台主要有两方面作用:首先是与企业自身的客户进行交流或是向客户宣传推广自己的品牌;其次是用于企业内部交流,利用短信平台向员工发送短信通知,例如会议通知、生日祝福等[6-7]。
现如今,随着互联网的高速发展,互联网企业的客户量也急剧增加。面对如此庞大的客户群体,企业内短信下发服务的压力也与日俱增[8-9]。针对这一问题,本文开发了基于Dubbo框架的短信平台,其采用了Dubbo框架实现分布式架构,将短信服务注册在zk中心,当有业务需要进行短信下发操作时则通过zk中心发现并消费服务。当短信下发需求量继续增加时,则可以通过在zk中心继续注册提供短信业务的服务器即可。文中以公司自身短信平台的实际开发为例,设计与实现了第三方支付短信平台的核心功能部分,主要包括短信核心模块、定时器模块等。
文中所开发的第三方支付短信平台,通过调用短信代理商接口来实现短信的发送。这样可以让项目开发的侧重点放在业务需求解决上,而无需关心短信如何具体下发。在这种接入模式下,以短消息平台下发给手机用户信息为例,短消息下发流程为:短信平台—短信代理商—短信运营商—手机用户。
该第三方支付短信平台中采用Spring MVC分层框架,通过RPC协议的Dubbo框架将公司业务逻辑层与短信平台服务层进行解耦,实现分布式架构[10]。如图1所示,本系统由四个层次模块组成,分别是业务接入层、短信服务层、基础服务层以及数据存储层。接入层主要是接受公司不同业务短信下发的请求,调用短信服务层对外提供的接口,从而实现短信下发功能;短信服务层在处理短信下发前则会根据短信通道路由策略,选择不同短信下发通道进行请求处理;基础服务层主要是为该短信平台系统提供一些的基础服务,例如消息服务、缓存服务以及日志服务等;数据存储层主要是对数据库进行操作,将操作比较频繁的数据保存在Redis缓存数据库中,而对于其他一些数据则保存在Mysql数据库中。
图1 系统架构图
图2 短信平台部署架构
该短信平台系统采用Spring MVC框架,不同层次之间采用依赖注入的方式进行分离解偶,使得各个层次容易进行定制,提高了系统性能,也增强了系统的扩展性能。同时,使用Dubbo框架也可以将短信服务层与接入层进行分离,将短信下发服务注册到Zookeeper中心并对外暴露服务。业务接入层需要短信下发操作时,通过在注册中心上发现并消费短信服务即可。基础服务中的消息服务采用的是RabbitMQ,由于短信下发数量巨大,每条短信下发成功后立即存入数据库中会极大的影响系统性能,若数据库出现异常状况也会导致短信入库记录异常。因此,本系统中采用RabbitMQ作为消息队列,短信下发成功后,将信息放入消息列队中,再由消息队列异步的进行入库操作。数据存储层采用的是Mybatis框架。
根据第三方支付短信平台系统设计的要求,以及对系统各方面性能要求的把握,形成了该第三方支付短信平台系统总体架构,如图2所示。
其中,接入层与短信服务层通过Dubbo框架解耦,并通过zk中心联系起来,而Dubbox监控系统则负责管理Dubbo服务。消息服务通过RabbitMQ实现,其每成功发送一条短信就异步的将短信发送结果下发到消息队列中,再从消息队列中写入到数据库中,从而减少了系统负担以及数据库异常所带来的问题。数据库缓存由redis来完成,其将操作频繁的数据保存在redis中,大幅提高了数据操作的速率和系统性能。在Zookeeper中,使用Zabbix对系统CPU、内存等的使用情况进行管理监控。
系统短信发送时序,如图3所示。
图3 短信发送时序图
短信发送流程如图4所示,当有短信下发请求时,业务平台首先会通过类Smscontroller接收业务平台传送的请求参数,包括手机号、短信内容等并调用SmsFacade短信下发接口sendSms()方法。该接口由类SmsFacadeImpl进行实现,同时在该实现类中通过路由策略选出具体短信下发通道,在具体通道中将短信发出。
具体通道下发流程:从配置中心获取已经设置好的该指定通道的用户名、密码以及请求地址(短信代理商提供),接着根据具体通道所指定的报文格式进行拼装参数Params。最后,通过doPost方法进行下发短信请求,代码如下:
wsdlUrl_ww为微网通联短信通道的url地址,"/g_Submit"为短信下发命令,相应的"/Sm_GetRemain"为短信余额查询命令。Params为拼装接口所需参数,responseStr则是微网通联响应信息。通过将responseStr字符串转为XML解析后,得到State参数,若为“0”则表示响应成功。
图4 短信下发流程图
2.2.1 短信通道的路由策略
本短信平台目前对接了5个短信代理商(大汉三通、建周等),即为5个短信通道。根据每个短信通道的收费、发送速率、到达率等因素为不同的通道划分优先级和权重。因此,当有短信下发请求时,短信平台的路由策略可以先根据短信通道的优先级进行选择,级别越高则优先选择。当优先级相同时,则再依据权重大小进行选择。同时,若以后需要增加短信通道,只需配置通道的优先级与权重即可,为企业今后的短信通道接入提供了便利。具体代码如下所示:
RouteStrategyCacheFacaderouteStrategyCacheFac ade=(RouteStrategyCacheFacade)
通过以上代码,将所有短信通道按照优先级和权重进行排序,将排序后的结果放入route StrategyList集合当中。arrayFlag[currentSmsFlag]代表当前通道,将SERVER_KEY+"_"+arrayFlag[currentSmsFlag]这一参数传入serverCache.get()方法可唯一确定短信下发的具体通道。当currentSmsFlag所代表的当前通道发送失败,则将currentSmsFlag+1来获取下一个通道重新下发短信。若仍然失败,则以此类推直到routeStrategyList当中的所有通道全部执行完成。
2.2.2 短信通道自动降级
由于目前短信平台对接了5个短信通道,每个通道也分配了优先级和权重。在选择具体通道时,会优先选择优先级高、权重大的通道[11]。但由于分配的优先级与权重是在理论基础上的设值,所以在实际项目中会依据短信通道下发短信的质量(主要指发送成功率)进行相应调整。当优先级高的通道发送短信失败条数达到设定值后,短信平台则会自动降低该通道的优先级或权重,从而减少系统因发送失败再重新发送而增加的负担。同时,也可以将失败的短信条数控制在相当低的水平,提高业务服务水平,增加客户友好度。
2.2.3 个性化短信业务
当消费者需要个性化业务时,比如(彩铃提示、语音提示),则短信平台会优先选择在该业务上与公司合作密切的短信通道进行发送。通过smsSendVo.getBusinessType()方法获取客户所需发送的业务类型,若是与短信类型所对应的code不匹配,则由通过该业务类型的指定通道进行发送。
通道报警主要实现定时调度,即基于时间点、间隔时间以及执行次数的任务调度过程[12]。在如今各式各类的业务系统中,基本上均存在周期性的任务需求,只要存在周期性的任务就离不开定时调度。在Java语言中,定时调度的实现方式主要有3种,分别为:Timer调度、线程池调度和Quartz调度[13-15]。
Timer调度简单方便,实现过程也相对简便,能实现简单的调度需求。但时间设置上不灵活,且以单线程方式运行,若出现异常容易挂起。
Quartz调度的配置也灵活简便,可以实现复杂的调度需求。Quartz采用的是多线程的调度方式,因而可以多任务并发执行。Quartz的另一显著优点在于持久化,即将任务调度的相关数据保存下来。这样,当系统重启后,任务被调度的状态依然存在于系统中,不会丢失。Quartz任务调度的核心元素是scheduler、trigger和 job,其中 trigger和 job是任务调度的元数据,scheduler是实际执行调度的控制器。
线程池调度以线程池为基础实现调度,是目前比较完美的定时调度。线程池采用的是多线程的调度方式,因而可以允许多任务并发执行;线程池中增加了守护线程来监测工作线程的生命状态,因而即使在极端复杂环境中也不存在调度任务会突然中断的问题。而缺点是配置比较复杂。
在本项目中,考虑到有5个短信通道需要实现定时调度,为防止不同通道之间的定时任务互相影响,所以采用多线程的调度方式。另外,该系统中不存在其他定时调度任务,故调度环境并不复杂,所以选择采用Quartz调度实现定时报警功能。
每个通道内公司均会预先充值一定的金额,每走相应的通道发送短信均会在该通道扣除相应的费用。当通道内余额不足时,就会导致下发短信失败,从而影响客户收到短信的速率。因此必须时刻了解通道内的余额状况,减少因余额不足而导致的短信下发失败。若是采用人工监督的方式,不仅费时费力,且准确率也没有保障。因此,采用了Quartz定时器进行监听,每隔一定时间查看一下余额,确保余额大于设定值。一旦小于设定值,则产生报警,提醒负责人进行充值。
文中首先,通过TaskAddMonitor类负责添加任务并启动任务。然后,采用QuartzManager定时任务管理类负责添加或移除定时任务,修改定时任务触发时间等。最后,通过TaskJobManager类实现了org.quartz.Job接口,可以使Java类变成可执行的,当匹配到已有的定时任务时则执行指定通道定时任务。
现如今,随着互联网的高速发展,互联网企业的客户量也急剧增加。面对如此庞大的客户群体,企业内短信下发服务的压力也与日俱增。针对这一问题,本文开发了基于Dubbo框架的短信平台,其采用了Dubbo框架实现分布式架构,将短信服务注册在zk中心,当有业务需要进行短信下发操作时则通过zk中心发现并消费服务。当短信下发需求量继续增加时,则可以通过在zk中心继续注册提供短信业务的服务器即可。本文以短信平台的实际开发为例,设计与实现了第三方支付短信平台的核心功能部分,主要包括短信核心模块、定时器模块等。