王 睿,趙 勇
(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中心繼續注冊提供短信業務的服務器即可。本文以短信平臺的實際開發為例,設計與實現了第三方支付短信平臺的核心功能部分,主要包括短信核心模塊、定時器模塊等。