程婷婷 胡煒薇 崔佳冬
(杭州電子科技大學(xué)新型電子器件與應(yīng)用研究所 浙江 杭州 310018)
現(xiàn)在城市規(guī)模越來越大,路燈等亮化照明設(shè)施越來越多,面對供電的緊張形勢帶來的資源浪費和人們?nèi)粘I畹呢撁嬗绊?,遠程控制路燈成為未來照明的發(fā)展趨勢。監(jiān)控系統(tǒng)較高的用戶體驗,使用的便捷性以及穩(wěn)定性被推上了更高的臺階。
監(jiān)控系統(tǒng)從過去的單機監(jiān)控發(fā)展到當(dāng)前的網(wǎng)絡(luò)監(jiān)控,網(wǎng)絡(luò)通信技術(shù)在遠程監(jiān)控技術(shù)中發(fā)揮著重要的作用[1]。傳統(tǒng)的路燈遠程監(jiān)控系統(tǒng)[2-3],控制方式智能方便,但并不適用于Web高并發(fā)訪問量的情況。目前,大多數(shù)照明管理系統(tǒng)數(shù)據(jù)存儲[4-6]使用的是關(guān)系型數(shù)據(jù)庫,而對于高并發(fā)和超大規(guī)模的動態(tài)網(wǎng)站,單一的關(guān)系型數(shù)據(jù)庫顯得力不從心。在Linux環(huán)境下[9]采用Nginx和Redis搭建分布式服務(wù)集群[7],能夠提升查詢的性能[8],有效解決高并發(fā)的Web需求。
對于單一的Web 服務(wù)器,瀏覽器的每個連接請求,服務(wù)器通常會為其創(chuàng)建一個進程或線程。這種方式存在一個很大的問題,由于創(chuàng)建進程或線程需要消耗大量資源和內(nèi)存,當(dāng)連接數(shù)太大時,這很容易使得內(nèi)存占用過大,很難準確及時響應(yīng)高并發(fā)量的訪問請求。本文提出了一個基于服務(wù)器集群的路燈遠程控制管理的設(shè)計方案。由于Nginx1.9.0發(fā)布后,Nginx開始支持TCP的負載均衡,本文利用Nginx的負載均衡策略[10]分別處理HTTP和TCP高并發(fā)請求,用Redis作為Mysql數(shù)據(jù)庫的緩存數(shù)據(jù)庫,以Redis和關(guān)系型數(shù)據(jù)庫配合的方式存儲數(shù)據(jù)。當(dāng)用戶查詢數(shù)據(jù)時,服務(wù)器先去訪問Redis,若Redis沒有相關(guān)數(shù)據(jù)返回,服務(wù)器則去訪問Mysql數(shù)據(jù)庫,并同時把查詢結(jié)果更新到Redis數(shù)據(jù)庫。
圖1中,集中器通過向服務(wù)器間隔發(fā)送固定心跳包的方式維持長連接。用戶通過瀏覽器客戶端登錄管理系統(tǒng),用戶登入系統(tǒng)后,通過瀏覽器可以管控集中器下的路燈。用戶將請求提交到Web服務(wù)器進行后臺處理,Web服務(wù)器將命令轉(zhuǎn)發(fā)給Socket服務(wù)器,再由Socket服務(wù)器將命令發(fā)送到指定的集中器,最終集中器收到命令執(zhí)行操作。
圖1 系統(tǒng)總體框架圖
云服務(wù)器使用Nginx作為反向代理來實現(xiàn)服務(wù)器負載均衡的功能。通過配置負載均衡可以組建Web服務(wù)集群,用戶請求通過Nginx反向代理轉(zhuǎn)發(fā)給后臺服務(wù)器集群,分擔(dān)了服務(wù)器的壓力。使用Redis存儲Nginx負載均衡集群的Session, 解決運行在不同容器里出現(xiàn)的Sesssion不同步或則容易丟失的問題,使云服務(wù)器在高并發(fā)的情況下能夠快速響應(yīng)用戶請求。
云服務(wù)器的功能模塊劃分為五個部分,如圖2所示。
圖2 云服務(wù)器功能模塊圖
(1) 用戶管理用戶第一次使用時,需要注冊賬號。短信驗證碼功能采用第三方短信驗證接口,通過比較手機收到的驗證碼與用戶頁面填入的驗證碼是否匹配進行驗證。根據(jù)用戶角色和權(quán)限的對應(yīng)關(guān)系設(shè)置用戶權(quán)限。
(2) 實時監(jiān)控遠程登錄系統(tǒng),監(jiān)測路燈如電壓、電流、電量、功率等實時運行參數(shù)。實時控制是控制系統(tǒng)的核心模塊,包括實時數(shù)據(jù)與歷史數(shù)據(jù)的查詢、實時控制路燈的開關(guān)和獲取路燈的實時參數(shù)信息。用戶點擊頁面按鈕,可以單燈控制,也可以批量控制。
(3) 設(shè)備檔案管理對整個項目監(jiān)控單元的檔案資料進行管理,通過瀏覽器對設(shè)備終端資料進行添加、查詢、修改和刪除。
(4) 告警管理當(dāng)某個設(shè)備終端出現(xiàn)故障后,系統(tǒng)通過短信告知工作人員故障的地點,工作人員能夠及時維修路燈。
(5) 統(tǒng)計分析用統(tǒng)計圖和表格展現(xiàn)某一集中器下路燈的工作情況,用戶通過選擇集中器號和時間點可以查詢相對應(yīng)的電壓、電流、用電量等參數(shù)。其中統(tǒng)計模塊包括日報表、月報表、每小時耗電量。
Nginx使用一個主進程來管理多個工作進程,每個工作進程都處于工作狀態(tài)負責(zé)提供互聯(lián)網(wǎng)服務(wù),工作進程間通過內(nèi)存共享等進程間通信機制實現(xiàn)Nginx的負載均衡等功能,主進程則主要負責(zé)監(jiān)控管理工作進程。進程間關(guān)系如圖3所示。
圖3 Nginx進程間關(guān)系
(1) HTTP負載均衡的配置
http {
upstream live_node {
server ×××;
server ×××;
server ×××;}
#×××這里為Nginx轉(zhuǎn)發(fā)的服務(wù)器IP地址和端口號
server {
listen 80;#監(jiān)聽HTTP的端口
server_name localhost;
location / {
root html;
index index.html index.htm;
proxy_pass http:#live_node;
}}}
(2) TCP負載均衡的配置
stream {
upstream rtmp {
server ×××;
server ×××;
server ×××; }
# ×××這里為Nginx轉(zhuǎn)發(fā)的服務(wù)器IP地址和端口號
server {
listen 1935; #需要監(jiān)聽TCP的端口
proxy_timeout 20s;
proxy_pass rtmp;
}}
通信模塊為本設(shè)計的核心模塊。瀏覽器有操作集中器的指令時,Web服務(wù)器將請求轉(zhuǎn)發(fā)到Socket服務(wù)器,用戶通過瀏覽器下達指令或者查詢數(shù)據(jù)。當(dāng)發(fā)送控制指令時,直接通過Socket服務(wù)器轉(zhuǎn)發(fā)指令,當(dāng)查詢數(shù)據(jù)時,直接從數(shù)據(jù)庫中讀取。
系統(tǒng)的通信模塊流程圖如圖4所示。
圖4 系統(tǒng)的通信模塊流程圖
2.3.1HTTP通信
用戶登錄、注冊、獲取設(shè)備信息都是基于HTTP通信主動建立連接。HTTP服務(wù)器采用Spring、Strust2 和Mybatis 框架,頁面主要是通過表單和AJAX(Asynchronous JavaScript And XML)提交數(shù)據(jù),服務(wù)器以JSON(JavaScript Object Notation)的數(shù)據(jù)格式返回。使用Strust2 的ModelDriven
(1) 從瀏覽器獲取燈的對象。
private LampDOO lampdoo = new LampDOO();
public LampDOO getModel() {return lampdoo;}
(2) 參數(shù)封裝到對象里。
CenterCommand cen = new CenterCommand();
cen.setEquipment(lampdoo.getEquipment()) ;
cen.setCenterId(lampdoo.getCenterId());
(3) 當(dāng)頁面點擊頁面的Button時,將參數(shù)傳遞到Socket服務(wù)器,CallResultDO驗證是否成功發(fā)送,若成功發(fā)送更改網(wǎng)頁顯示信息。
CallResultDO cr = blockChannel.blockSend
(lampdoo.getCenterId(), cen);
//輸出接收到的數(shù)據(jù)
if ( cr.isSuccess() ){this.request.setAttribute(″result″,
new String(cr.getData()));
this.request.setAttribute(″commit″, ″true″);}
2.3.2TCP通信
集中器和云端的通信是基于TCP/IP的通信。Socket服務(wù)器采用MINA(Multipurpose Infrastructure for Network Applications)框架,用戶通過調(diào)用接口便可以開發(fā)高性能、高擴展性的網(wǎng)絡(luò)通信服務(wù)器。當(dāng)有客戶端向Socket服務(wù)器發(fā)送請求時,客戶端的地址和端口與服務(wù)端的地址和端口構(gòu)成一個Session。MINA把Session封裝成IoSession接口,服器端通過IoSession能夠區(qū)分是哪個客戶端的請求,從而保持服務(wù)器和客戶端之間的正常通信。集中器和Socket服務(wù)器通信采用應(yīng)用層定時發(fā)送心跳包的方式保持連接的存活,保證通信的可靠性。
(1) 處理接收到的數(shù)據(jù)集中器向服務(wù)器傳輸?shù)乃卸M制信息都存放在IoBuffer中:byte[] data=CommandUtils.ioBufferToByte(message)。
(2) 對數(shù)據(jù)的粘包和斷包進行處理集中器傳輸?shù)椒?wù)器上的通信協(xié)議由協(xié)議頭、數(shù)據(jù)頭、數(shù)據(jù)體、協(xié)議尾組成。其中,協(xié)議頭、數(shù)據(jù)頭、協(xié)議尾是固定值段。為了保證協(xié)議頭、數(shù)據(jù)頭和協(xié)議尾不會出現(xiàn)在長度字段和數(shù)據(jù)體中,使用擴展技術(shù)。數(shù)據(jù)體由原始數(shù)據(jù)經(jīng)過Base64編碼得到,長度字段是對占4個字節(jié)空間的整形長度進行擴展后得到的。比如對0x1A進行擴展,擴展后占2個字節(jié),值分別為1 和A的ASCII(American Standard Code for Information Interchange)碼值0x31和0x41,避免了識別協(xié)議頭和協(xié)議尾的錯誤,保證了程序的正確性。解析數(shù)據(jù)時,對符合要求的數(shù)據(jù)體放入Datas中,對于斷包和粘包不完整的數(shù)據(jù)分別放入bufferData和leftData里,同下一次接收的數(shù)據(jù)合并處理。
if(leftData!=null){data = CommandUtils.byteMerger
(leftData,data) ;
session.removeAttribute(″leftData″);}
if ( null != buffData )
{data = CommandUtils.byteMerger(buff,data);}
//分析數(shù)據(jù)包,將對應(yīng)字段放入對象中
CenterCommand receive = CenterCommand.analyse
Package(data , session);
//解析數(shù)據(jù)體
CenterCommand center = CenterCommand.
analyseCommand(receive.getDatas());
(3) 對處理后的完整數(shù)據(jù)包進行命令解析
if( center.getCommand() == 101 ) { //實時通信通道
WebCommand t = WebCommand.analyseCommand
(center);//解析數(shù)據(jù)
blockChannel.syncput(web.getEquipment(),web.
getData().getBytes());
//數(shù)據(jù)寫入內(nèi)存
ResultData result = ResultData.createResultData(center.
getVersion(),center.getCommand(), 2);
byte[] redata = result.renderData();
redata = ResultData.renderData(redata);
IoBuffer rib = IoBuffer.allocate(redata.length);
rib.put(redata,0,redata.length);
rib.flip();
session.write(rib);
return;}
//對集中器進行回復(fù)
數(shù)據(jù)庫使用Mysql和Redis。Redis作為Mysql的緩存數(shù)據(jù)庫,減小了Mysql的壓力,在數(shù)據(jù)量大、高并發(fā)的情況下,提高了系統(tǒng)的處理效率。實現(xiàn)負載均衡時,用戶每一個請求都有可能被分配到不固定的服務(wù)器上,先要解決Session的統(tǒng)一問題,無論用戶的請求被轉(zhuǎn)發(fā)到哪個服務(wù)器上都能保證用戶的正常使用,即需要實現(xiàn)Session的共享機制。將Session存到Redis中,以這種方式來同步Session。通過將Session存放到內(nèi)存級數(shù)據(jù)庫里,加快讀取速度,解決用戶訪問不同服務(wù)器時Session的共享問題。數(shù)據(jù)庫架構(gòu)如圖5所示。
圖5 數(shù)據(jù)庫架構(gòu)
修改Redis安裝包里conf目錄下的content.xml,對Redis進行配置,如下所示:
redissessions.RedisSessionHandlerValue″/> redissessions.RedissessionManager″ host = ″106.14.9.111″#Redis服務(wù)器地址 port = ″6379″#Redis的端口號 database = ″0″#Redis數(shù)據(jù)庫的標志 maxInactiveInterval = ″1 800″/> #Redis過期時間默認是60秒,Session過期時間為30分鐘,這里需要設(shè)置為1 800對應(yīng)30分鐘。 百度地圖API提供基本地圖展現(xiàn)、搜索、定位等功能,定位精確度高、覆蓋率廣。本系統(tǒng)調(diào)用百度地圖的接口將集中器下的路燈的信息通過地圖實時顯示,紅色實心形狀代表正在運行的集中器,藍色表示沒有運行的集中器,以不同的顏色和形狀表現(xiàn)出來,直觀清晰。使用AJAX方法完成前端頁面和后臺服務(wù)器的交互,將集中器的相關(guān)信息返回并在頁面上顯示出來。 //創(chuàng)建標簽 var label = new window.BMap.Label(data[i].equipment, {offset: new window.BMap.Size(20, -10) }); marker[i].setLabel(label); //添加標簽 // 創(chuàng)建信息窗口對象 info[i]=new window.BMap.InfoWindow(″ ″+data[i]. equipment+″經(jīng)度:″+data[i].longitude+″ 緯度:″+data[i].latitude +″連網(wǎng)狀態(tài):″+data[i].online +″ 集中器號:″+data[i].centerId+″ 使用壓力測試工具Httperf和Autobench在Linux環(huán)境下分別對單一服務(wù)器和服務(wù)器集群的系統(tǒng)性能進行測試。服務(wù)器集群由4臺第三方云服務(wù)器組成,其中1臺服務(wù)器作為Nginx負載均衡服務(wù)器,其他3臺作為Tomcat服務(wù)器,4臺服務(wù)器的系統(tǒng)是Centos6.8,Nginx使用的版本是1.10.3。測試命令如下: Autobench --single_host --host1=主機地址 --uri1=測試的uri --port1=端口號 --quiet --low_rate=100 --high_rate=500 --rate_step=10 --num_call=1 --num_conn=300 --timeout=10 --file /opt/nginx.tsv 本測試通過在并發(fā)連接數(shù)相同的情況下,比較單一服務(wù)器和集群服務(wù)器處理請求的響應(yīng)時間,測試單一服務(wù)器和集群服務(wù)器的并發(fā)能力。測試結(jié)果如表1所示,相應(yīng)的圖如圖6所示。 表1 單一服務(wù)器和集群服務(wù)器響應(yīng)時間 圖6 單一服務(wù)器和集群服務(wù)器響應(yīng)時間 從表1和圖6可以看出,隨著并發(fā)連接的增加,單一服務(wù)器響應(yīng)時間變慢;而對于集群服務(wù)器,隨著并發(fā)連接數(shù)的增加,響應(yīng)時間變化很小。單一服務(wù)器能夠處理并發(fā)連接數(shù)在300左右,而集群服務(wù)器能夠處理的并發(fā)連接數(shù)遠遠大于單一服務(wù)器。很明顯,集群服務(wù)器提升了系統(tǒng)的性能,適合處理高并發(fā)請求。 瀏覽器客戶端具有人機交互,界面友好的用戶界面,方便用戶管理。用戶通過瀏覽器可以控制設(shè)備開關(guān),通過點擊頁面按鈕,將指令下達給網(wǎng)絡(luò)調(diào)試助手,網(wǎng)絡(luò)調(diào)試助手以16進制顯示,如圖7所示。 圖7 設(shè)備控制界面 通過地圖可以直觀地看到路燈安裝在哪個位置。點擊地圖上的標點,能夠查看該位置路燈狀態(tài)等相關(guān)信息,如圖8所示。 圖8 路燈遠程監(jiān)控系統(tǒng)地圖顯示 使用Hightcharts對路燈的歷史數(shù)據(jù)進行繪圖,并用表格的形式展現(xiàn)出來,使用戶對路燈參數(shù)一目了然,方便查詢、管理。路燈歷史電量統(tǒng)計如圖9所示。 圖9 路燈歷史電量統(tǒng)計 本文設(shè)計并實現(xiàn)了基于服務(wù)器集群的路燈遠程監(jiān) 控管理軟件。基于Nginx對前端Web高并發(fā)訪問和設(shè)備TCP通信分別實現(xiàn)負載均衡。使用Redis和關(guān)系型數(shù)據(jù)庫配合的方式存儲數(shù)據(jù),實現(xiàn)Session變量的共享,有效解決高并發(fā)需求的問題,提高系統(tǒng)的可靠性。用戶通過瀏覽器查看路燈地理位置和向服務(wù)器發(fā)送控制指令,實現(xiàn)用戶隨時隨地遠程監(jiān)控路燈。 [1] 鄭黎明.計算機通信與網(wǎng)絡(luò)遠程控制技術(shù)探討[J].信息通信,2016(10):163-164. [2] 張卿杰,徐友,薛國慶.基于Web Service的無線路燈遠程監(jiān)控系統(tǒng)[J].現(xiàn)代電子技術(shù),2015(11):5-9. [3] 季建華.基于物聯(lián)網(wǎng)的智能家居遠程監(jiān)控系統(tǒng)設(shè)計與實現(xiàn)[J].計算機應(yīng)用與軟件,2015,32(11):143-146. [4] 劉蒙蒙.基于物聯(lián)網(wǎng)的城市道路照明管理系統(tǒng)設(shè)計與開發(fā)[D].合肥工業(yè)大學(xué),2015. [5] 陳嘉琪,肖純,柯志雄.基于Web的路燈智能監(jiān)測系統(tǒng)[J].工業(yè)控制計算機,2016,29(5):123-124. [6] 余鐘源.城市照明智能監(jiān)控系統(tǒng)的研究[D].北京郵電大學(xué),2015. [7] 蒲曉陽.基于Nginx和Redis高并發(fā)web服務(wù)負載均衡的研究[J].內(nèi)江科技,2016,37(1):40-40. [8] Wu X,Long X,Wang L.Optimizing Event Polling for Network-Intensive Applications:A Case Study on Redis[C]//International Conference on Parallel and Distributed Systems.IEEE Computer Society,2013:687-692. [9] 金明哲,鄭建立,裴旭明,等.應(yīng)用于物聯(lián)網(wǎng)的Linux云端服務(wù)器設(shè)計[J].信息技術(shù),2015(9):179-183. [10] Kovalev A,Otrashkevich K,Sidorov E,et al.Effusion-a new sophisticated injector for Nginx web servers[J].Computer Networks,2014,56(12):2800-2807.2.5 終端實時監(jiān)控設(shè)計
3 測試與分析
3.1 服務(wù)器性能測試
3.2 界面展示
4 結(jié) 語