莊學(xué)松 張 智 黃可望
(無錫職業(yè)技術(shù)學(xué)院 a.物聯(lián)網(wǎng)技術(shù)學(xué)院; b.人事處; c.物聯(lián)網(wǎng)技術(shù)學(xué)院,江蘇 無錫 214121)
為了保護(hù)氣象值班人員的眼睛,降低值班人員的工作強(qiáng)度,各種業(yè)務(wù)系統(tǒng)的狀態(tài)監(jiān)控和報(bào)警系統(tǒng)相繼開發(fā)。及時(shí)的短信報(bào)警通知讓裝備設(shè)備的維修更加及時(shí),解決問題的效率也更加高效。短信報(bào)警功能在實(shí)際的業(yè)務(wù)系統(tǒng)運(yùn)行中發(fā)揮了重要的作用。
目前,大部分氣象部門技術(shù)人員采用的短信報(bào)警方式是利用短信貓進(jìn)行消息的通知,其在開發(fā)和維護(hù)時(shí)難度較高,并且在發(fā)送短信的時(shí)容易遇到一些底層難以定位的問題。為了進(jìn)一步開發(fā)短信報(bào)警功能,急需重新對短信發(fā)送的方案進(jìn)行改造,使氣象各級單位的技術(shù)人員都能簡單方便地調(diào)用短信發(fā)送功能而無需關(guān)注底層的發(fā)送指令。
微服務(wù)是一種構(gòu)建應(yīng)用程序的體系結(jié)構(gòu)方法。作為一個(gè)架構(gòu)框架,微服務(wù)呈分布式且松散耦合結(jié)構(gòu),因此,一個(gè)子部件的更改不會(huì)破壞整個(gè)應(yīng)用程序。使用微服務(wù)的好處是開發(fā)團(tuán)隊(duì)能夠快速構(gòu)建應(yīng)用程序的新組件,以達(dá)到乃至引領(lǐng)業(yè)務(wù)需求。與傳統(tǒng)方法相比,微服務(wù)架構(gòu)將應(yīng)用分解為核心功能的幾個(gè)功能模塊,每個(gè)功能都稱為服務(wù),并且可以獨(dú)立構(gòu)建和部署,這意味著單個(gè)服務(wù)運(yùn)行的失敗并不會(huì)對其他服務(wù)產(chǎn)生影響[1]。
由于當(dāng)前各行政級別的氣象部門存在大量自己開發(fā)的系統(tǒng),這些系統(tǒng)在各部門間不共享資源,對于各自業(yè)務(wù)系統(tǒng)的狀態(tài)監(jiān)控信息和報(bào)警信息缺少共享機(jī)制,開發(fā)資源和技術(shù)也同樣缺少共享和交互機(jī)制。同時(shí),以前的系統(tǒng)都是“整體式”的開發(fā)方法,即使對已有業(yè)務(wù)系統(tǒng)進(jìn)行最小的改動(dòng),也需要對整個(gè)系統(tǒng)進(jìn)行重新編碼、驗(yàn)證及發(fā)行。此方式將源代碼編譯打包在一個(gè)壓縮文件中,網(wǎng)站程序文件一般為War文件。如果應(yīng)用系統(tǒng)中的一部分程序出現(xiàn)錯(cuò)誤,則會(huì)影響整個(gè)系統(tǒng)中的其他單元。微服務(wù)的思想是將一個(gè)大系統(tǒng)拆成幾個(gè)小系統(tǒng),每個(gè)系統(tǒng)只需要關(guān)注自己的業(yè)務(wù)邏輯即可。多人可以同時(shí)開發(fā)同一個(gè)系統(tǒng)的中的不同單元,每個(gè)單元之間通過流行的RPC框架進(jìn)行通信[2]。
目前主要的短信方式包括兩種,短信貓發(fā)送和網(wǎng)絡(luò)接口調(diào)用。利用短信貓發(fā)送硬件進(jìn)行發(fā)送需要外接電源及手機(jī)通信卡,在連接設(shè)備后可在電腦上通過廠家公開的AT指令或更上層的短信操作API實(shí)現(xiàn)短信發(fā)送。隨著后端服務(wù)技術(shù)的發(fā)展及移動(dòng)運(yùn)行商短信接口的開放,網(wǎng)絡(luò)接口調(diào)用的方式逐漸流行起來。在系統(tǒng)前期的研究過程中采用的是第一種方案,該方案的優(yōu)點(diǎn)是發(fā)送短信快速、穩(wěn)定、開發(fā)和使用不受除移動(dòng)運(yùn)行商外的第三方限制,其缺點(diǎn)是需要購買硬件并理解底層的AT指令,開發(fā)周期相對較長。網(wǎng)絡(luò)短信服務(wù)接口的最主要特點(diǎn)是短信發(fā)送的底層細(xì)節(jié)不需要關(guān)心,只需要了解短信服務(wù)提供商的接口協(xié)議即可。但是該方案嚴(yán)重依賴于網(wǎng)絡(luò),如果網(wǎng)絡(luò)不通則完全無法使用。目前大多數(shù)系統(tǒng)還是采用硬件的方式發(fā)送短信,該方案在使用過程中發(fā)現(xiàn)對AT指令的理解和具體短信貓的特性需要理解得比較透徹才能發(fā)揮出優(yōu)勢,否則雖然實(shí)現(xiàn)了短信發(fā)送的功能,但是在收發(fā)短信的時(shí)效性和易用性上卻無法滿足業(yè)務(wù)應(yīng)用的需求。
在先前系統(tǒng)的實(shí)施方案中采用短信貓直接發(fā)送短信,但是在使用一段時(shí)間后發(fā)現(xiàn)某些短信貓不支持全網(wǎng)通,有些短信貓發(fā)送短信時(shí)間需要耗時(shí)幾分鐘,后期更換短信貓還需要更改代碼層面的AT指令,因此需要在之前系統(tǒng)結(jié)構(gòu)的基礎(chǔ)上將短信貓更換為速度快、性能穩(wěn)定、資費(fèi)更低的網(wǎng)絡(luò)短信接口。國內(nèi)有阿里云、深圳夢網(wǎng)、京東、創(chuàng)信等網(wǎng)絡(luò)短信服務(wù)提供商。本項(xiàng)目方案使用阿里云短信API來開發(fā)短信報(bào)警服務(wù)的基礎(chǔ)功能,圖1為改進(jìn)后的基于網(wǎng)絡(luò)短信服務(wù)接口結(jié)構(gòu)圖。
圖1 短信服務(wù)結(jié)構(gòu)
一臺(tái)可以聯(lián)網(wǎng)的電腦和阿里云短信服務(wù)接口組成了短信服務(wù)提供方,短信代理服務(wù)器通過阿里云短信服務(wù)器的API實(shí)現(xiàn)在線短信收發(fā)功能,外部通過Http地址的形式訪問Servlet接口。各部門單位原先的值班系統(tǒng)和應(yīng)用系統(tǒng)都不需要變化,這些系統(tǒng)作為短信內(nèi)容生產(chǎn)方的角色將各種報(bào)警信息放到隊(duì)列中[3]。
通過短信代理服務(wù)器解決了采用網(wǎng)絡(luò)短信服務(wù)必須要連通外網(wǎng)的缺點(diǎn),在省局內(nèi)只需一臺(tái)能上網(wǎng)的電腦并在上面部署短信發(fā)送代理程序即可使市局和縣局通過內(nèi)網(wǎng)直連接短信代理服務(wù)器發(fā)送和接收短信。
系統(tǒng)采用SpringBoot實(shí)現(xiàn)短信代理服務(wù)。微服務(wù)架構(gòu)的主要特征是去中心化和分布式結(jié)構(gòu)。它是將一個(gè)項(xiàng)目的各個(gè)模塊有序分割,之后由各模塊提供API,供其他功能模塊調(diào)用。各模塊一般都獨(dú)立運(yùn)行,而且有自己的數(shù)據(jù)庫與服務(wù)器,通過“化整為零”,各個(gè)模塊之間得到了解耦,系統(tǒng)的擴(kuò)展性更強(qiáng)。而SpringBoot就是進(jìn)行微服務(wù)架構(gòu)開發(fā)的一套框架工具,它是在Spring框架基礎(chǔ)上發(fā)展出來的,借助它可以真正做到前后端分離。
整個(gè)系統(tǒng)中短信生產(chǎn)方、短信服務(wù)使用方、短信服務(wù)提供方都可以按照微服務(wù)的思想進(jìn)行開發(fā)。這里主要介紹短信服務(wù)提供方實(shí)現(xiàn)微服務(wù)過程。
(1)在eclipse中創(chuàng)建一個(gè)maven應(yīng)用。
(2)引入SpringBoot框架,需在pom.xml文件中引入SpringBoot父容器并添加Web開發(fā)所需要的相應(yīng)依賴。主要包括jdk1.8;啟動(dòng)器父包spring-boot-starter-parent;web工程包spring-boot-starter-web;特定的網(wǎng)絡(luò)短信的包,如阿里云短信服務(wù)的包。
(3)創(chuàng)建SpringBoot引導(dǎo)類。
(4)創(chuàng)建配置文件 application.properties,對啟動(dòng)端口進(jìn)行配置,并配置網(wǎng)絡(luò)短信發(fā)送id、密鑰、短信簽名及短信模板名。
(5)創(chuàng)建發(fā)短信的工具類,其中調(diào)用阿里云短信服務(wù)的主要代碼如下:
//a、創(chuàng)建profile
//accessKeyId:申請的ID, accessKeySecret:申請的密鑰
IClientProfile pf = DefaultProfile.getProfile(STRING_CN_HZ", akID, akSecret);
DefaultProfile.addEndpoint(STRING_CN_HZ, STRING_CN_HZ, STRING_DYSMS, STRING_DYSMS_URI);
//b、創(chuàng)建client
IAcsClient acsClient= new DefaultAcsClient(pf);
//c、創(chuàng)建Request對象
SendSmsRequest rest = new SendSmsRequest();
//d、設(shè)置Request的參數(shù)
//mobile:待發(fā)送手機(jī)號(hào)
rest.setPhoneNumbers(mobile);
//signName:簽名
rest.setSignName(signName);
//templateCode:自定義的模板
rest.setTemplateCode(templateCode);
//code:變量信息
rest.setTemplateParam("{”code”:"+STRING_PARA+"}");
//e、用client對應(yīng)的方法傳入request,獲得response
SendSmsResponse returnValue = acsClient.getAcsResponse(rest);
//f、在response中獲得返回的參數(shù)值
return returnValue;
系統(tǒng)采用的網(wǎng)絡(luò)短信服務(wù)商為阿里云短信,主要接入流程如下[4]:
(1)到官網(wǎng)上開通短信服務(wù)。短信服務(wù)開通后需要獲取 accessKey和 accessKeySecret。
(2)創(chuàng)建簽名并等待官方審核(一般需要等待2個(gè)小時(shí)),簽名指的是短信前面顯示的名稱,比如“【氣象短信報(bào)警接口】短信正文....”中括號(hào)里面的就是簽名。
(3)創(chuàng)建短信發(fā)送模板并等待官方審核,模板就是短信的正文中不變的部分,再加上一部分參數(shù)輸入的描述。如,模版內(nèi)容: 報(bào)警等級為 {class},報(bào)警內(nèi)容為 {text}。其中有兩個(gè)變量,分別為class-等級和text-內(nèi)容。
(4)在簽名和短信模板審核通過后就能用這個(gè)模板發(fā)送短信,這與其他短信服務(wù)直接在身份驗(yàn)證后直接發(fā)送短信有所區(qū)別。
(5)根據(jù)業(yè)務(wù)應(yīng)用選擇合適的短信套餐。至此配置完成,可以利用阿里云短信服務(wù)的API發(fā)送短信。
阿里云短信服務(wù)API調(diào)用封裝后即可在短信代理處進(jìn)行調(diào)用,根據(jù)返回的結(jié)果判斷調(diào)用是否成功。在封裝后再發(fā)布成內(nèi)網(wǎng)中可以調(diào)用的Http服務(wù),即在內(nèi)網(wǎng)中也可以間接地調(diào)用阿里云短信服務(wù)。主要調(diào)用代碼如下:
CommonResponse returnValue = SMSsend(phoneNo,text);
if(returnValue != null && returnValue.getHttpStatus() == 200){
String data = returnValue.getData();
Map map = JSON.parseObject(data, Map.class);
LOGGER.info("send message status is:{}" + phone + "and text is" + text + "," + map.get("Text"));
短信服務(wù)接口通過HTTP的形式暴露外部調(diào)用接口。HTTP格式為:
http://Address:Port/smsSend/send?user=***&pwd=***&phoneNo=****&text=****&prior=***&token=****
Address和Port是服務(wù)提供方供外部訪問用的入口;user和pwd是對短信的使用者進(jìn)行身份鑒別,防止非法調(diào)用。只有在驗(yàn)證通過后才能調(diào)用阿里云服務(wù)封裝后的短信發(fā)送接口。
在報(bào)警事件產(chǎn)生時(shí)需要及時(shí)地推送給業(yè)務(wù)值班人員,值班人員根據(jù)報(bào)警內(nèi)容排查并解決問題。但并不是報(bào)警推送越多越好,需要把握一個(gè)度,不能漏掉重要信息,又不能頻繁推送信息影響值班人員對重要信息的判斷。頻繁推送報(bào)警內(nèi)容甚至?xí)Χ绦磐扑凸δ墚a(chǎn)生抵觸心理。因此需要針對不同等級,不同內(nèi)容制定詳細(xì)的頻次推送規(guī)劃,記錄每一個(gè)短信在一段時(shí)間內(nèi)推送到相關(guān)人員的頻次,當(dāng)達(dá)到一定的閾限后不能繼續(xù)推送報(bào)警信息。
除了在發(fā)生或即將發(fā)生報(bào)警事件時(shí)及時(shí)調(diào)用短信服務(wù)將報(bào)警內(nèi)容推送給指定人員外,還有其他的內(nèi)容需要短信推送給相關(guān)人員。如每個(gè)值班人員還關(guān)心每個(gè)整點(diǎn)的業(yè)務(wù)運(yùn)行情況是否正常,每天整體情況運(yùn)行如何,每月狀態(tài)統(tǒng)計(jì)信息如何。因此,需要定時(shí)將業(yè)務(wù)運(yùn)行情況、軟件和系統(tǒng)資源的運(yùn)行情況匯總并發(fā)給相關(guān)人員做實(shí)時(shí)監(jiān)控。對于定期推送的不同種類的短信需要精確地推送給指定的人員,不能推送出現(xiàn)混亂。如果因?yàn)榫W(wǎng)絡(luò)、接口服務(wù)器、軟件系統(tǒng)、機(jī)器等原因不能保證短信發(fā)送功能7*24小時(shí)連續(xù)工作,需要將發(fā)送的成功狀態(tài)、發(fā)送的記錄保存下來。
對于上述兩種情況采用Redis實(shí)現(xiàn)短信發(fā)送狀態(tài)的緩存。Redis是一種開源的鍵值數(shù)據(jù)庫,由于非常優(yōu)異的性能和可持久化的特性使得它被廣泛地應(yīng)用到各大網(wǎng)站服務(wù)平臺(tái)中[5]。SpringBoot中除了支持關(guān)系型數(shù)據(jù)庫Oracle、MySql、SqlServer外,也對Redis等非關(guān)系型數(shù)據(jù)進(jìn)行了自動(dòng)化支持。因此,在SpringBoot中利用集成的Redis組件可方便地對數(shù)據(jù)進(jìn)行CRUD操作。
國內(nèi)短信內(nèi)容計(jì)費(fèi)方案一般是根據(jù)短信內(nèi)容中的字?jǐn)?shù)進(jìn)行收費(fèi),如果短信字?jǐn)?shù)達(dá)到一定的長度(一般為70個(gè))就按多條短信進(jìn)行計(jì)費(fèi)。
一般情況下,網(wǎng)絡(luò)短信服務(wù)商對同一個(gè)手機(jī)號(hào)碼發(fā)送短信通知的條數(shù)有限制,比如阿里云短信服務(wù)支持50條/天。如果發(fā)送字?jǐn)?shù)超過限額后也會(huì)提示業(yè)務(wù)限流。單條短信字?jǐn)?shù)也有限制,一般達(dá)到500多個(gè)字,超限的話會(huì)發(fā)送失敗。
國內(nèi)短信支持全網(wǎng)通發(fā)送,并且支持向國際和中國的港澳臺(tái)運(yùn)營商的手機(jī)發(fā)送短信,但是一次最多發(fā)送的目的手機(jī)數(shù)目受限制,不同網(wǎng)絡(luò)運(yùn)營商可能不一樣,比如阿里云一次最多可向1 000個(gè)手機(jī)號(hào)碼發(fā)送短信。
基于Springboot實(shí)現(xiàn)短信報(bào)警的微服務(wù)系統(tǒng)結(jié)構(gòu),結(jié)合Redis 的主要特性,利用其優(yōu)異的數(shù)據(jù)庫條目讀寫效率的優(yōu)勢,實(shí)現(xiàn)了短信服務(wù)的快速調(diào)用,提高了整個(gè)系統(tǒng)的可維護(hù)性和用戶體驗(yàn)。
短信代理服務(wù)通過Http 方式發(fā)布接口供外部調(diào)用,通過接口的實(shí)現(xiàn)方可以實(shí)時(shí)反饋一些狀態(tài)信息,比如某個(gè)號(hào)碼發(fā)送頻率。后期設(shè)計(jì)可以在后端根據(jù)每個(gè)號(hào)碼的發(fā)送特性制作統(tǒng)計(jì)報(bào)表并可以進(jìn)行流量控制以防止惡意發(fā)送。