基于Java Netty框架構(gòu)建高性能的部標(biāo)808協(xié)議的GPS服務(wù)器
使用Java語(yǔ)言開(kāi)發(fā)一個(gè)高質(zhì)量和高性能的jt808 協(xié)議的GPS通信服務(wù)器,并不是一件簡(jiǎn)單容易的事情,開(kāi)發(fā)出來(lái)一段程序和能夠承受數(shù)十萬(wàn)臺(tái)車載接入是兩碼事,除去開(kāi)發(fā)部標(biāo)808協(xié)議的固有復(fù)雜性和幾個(gè)月長(zhǎng)周期的協(xié)議Bug調(diào)試,作為大批量794車載終端接入的服務(wù)端,需要能夠處理網(wǎng)絡(luò)的閃斷、客戶端的重連、安全認(rèn)證和消息的編解碼、半包處理等。如果沒(méi)有足夠的網(wǎng)絡(luò)編程經(jīng)驗(yàn)積累和深入了解部標(biāo)808協(xié)議文檔,自研的GPS服務(wù)器往往需要半年甚至數(shù)年的時(shí)間才能最終穩(wěn)定下來(lái),這種成本即便對(duì)一個(gè)大公司而言也是個(gè)嚴(yán)重的挑戰(zhàn)。
1)我們?cè)陂_(kāi)發(fā)部標(biāo)協(xié)議的GPS服務(wù)器,需要解決以下幾個(gè)問(wèn)題:
1. 通信服務(wù)器固有的連接管理,能夠處理網(wǎng)絡(luò)的閃斷、客戶端的重連、安全認(rèn)證和消息的編解碼、半包處理;
2. 海量終端接入的高并發(fā)性能;
3. 良好的內(nèi)存管理,車載終端的連接本事是基于GPRS的無(wú)線連接,車輛在野外高速移動(dòng)過(guò)程中,信號(hào)處于不穩(wěn)定狀態(tài),雖然是基于長(zhǎng)連接,但是這種連接不斷的中斷和接入,服務(wù)器在處理終端接入,數(shù)據(jù)解析,報(bào)警分析,批量入庫(kù)的時(shí)候,能夠內(nèi)存分配合理,不會(huì)造成內(nèi)存泄漏,在百萬(wàn)次的調(diào)用中不會(huì)造成內(nèi)存累計(jì)上升;
2)要開(kāi)發(fā)一個(gè)高性能的GPS服務(wù)器的三個(gè)主題:
1) 傳輸:用什么樣的通道將數(shù)據(jù)發(fā)送給對(duì)方,BIO、NIO或者AIO,IO模型在很大程度上決定了框架的性能。
2) 協(xié)議:采用什么樣的通信協(xié)議,HTTP或者內(nèi)部私有協(xié)議。協(xié)議的選擇不同,性能模型也不同。相比于公有協(xié)議,內(nèi)部私有協(xié)議的性能通常可以被設(shè)計(jì)的更優(yōu)。
3) 線程:數(shù)據(jù)報(bào)如何讀取?讀取之后的編解碼在哪個(gè)線程進(jìn)行,編解碼后的消息如何派發(fā),Reactor線程模型的不同,對(duì)性能的影響也非常大。
Netty是業(yè)界最流行的NIO框架,可以很好的解決上面三個(gè)問(wèn)題,它的可靠性、高性能和可擴(kuò)展性已經(jīng)得到了上百上千的商用項(xiàng)目驗(yàn)證,相對(duì)于.NET中的基于完成端口的通信框架,它要優(yōu)越的多,它的優(yōu)點(diǎn)總結(jié)如下:
1. API使用簡(jiǎn)單,開(kāi)發(fā)門檻低;
2. 功能強(qiáng)大,內(nèi)聚了很多實(shí)用的功能,簡(jiǎn)化用戶的開(kāi)發(fā);
3. 定制性好,通過(guò)ChannelPipeline機(jī)制可以靈活的進(jìn)行功能定制和擴(kuò)展;
4. 性能高;
5. 成熟穩(wěn)定,社區(qū)活躍,Bug的修復(fù)周期比較短,新功能不斷的被加入,用戶可以體驗(yàn)到更多、更實(shí)用的功能。
6. 經(jīng)歷了大規(guī)模不同行業(yè)的商用考驗(yàn),架構(gòu)質(zhì)量得到了充分的驗(yàn)證。
Netty為了向使用者屏蔽NIO通信的底層細(xì)節(jié),在和用戶交互的邊界做了封裝,目的就是為了減少用戶開(kāi)發(fā)工作量,降低開(kāi)發(fā)難度。ServerBootstrap是Socket服務(wù)端的啟動(dòng)輔助類,用戶通過(guò)ServerBootstrap可以方便的創(chuàng)建Netty的服務(wù)端。
3)編碼器和解碼器的設(shè)計(jì)
對(duì)于808協(xié)議的解析處理,需要編寫(xiě)自定義的解碼器了,目前Netty提供了多個(gè)基礎(chǔ)編碼器可以供開(kāi)發(fā)者進(jìn)行繼承和拓展,開(kāi)發(fā)的時(shí)候,需要了解這幾個(gè)解碼器的主要作用,主要用于那些通信數(shù)據(jù)傳輸?shù)膱?chǎng)景。
為了降低用戶的開(kāi)發(fā)難度,Netty對(duì)常用的功能和API做了裝飾,以屏蔽底層的實(shí)現(xiàn)細(xì)節(jié)。編解碼功能的定制,對(duì)于熟悉Netty底層實(shí)現(xiàn)的開(kāi)發(fā)者而言,直接基于ChannelHandler擴(kuò)展開(kāi)發(fā),難度并不是很大。但是對(duì)于大多數(shù)初學(xué)者或者不愿意去了解底層實(shí)現(xiàn)細(xì)節(jié)的用戶,需要提供給他們更簡(jiǎn)單的類庫(kù)和API,而不是ChannelHandler。
Netty在這方面做得非常出色,針對(duì)編解碼功能,它既提供了通用的編解碼框架供用戶擴(kuò)展,又提供了常用的編解碼類庫(kù)供用戶直接使用。在保證定制擴(kuò)展性的基礎(chǔ)之上,盡量降低用戶的開(kāi)發(fā)工作量和開(kāi)發(fā)門檻,提升開(kāi)發(fā)效率。
通常我們也習(xí)慣將編碼(Encode)稱為序列化(serialization),它將對(duì)象序列化為字節(jié)數(shù)組,用于網(wǎng)絡(luò)傳輸、數(shù)據(jù)持久化或者其它用途。
反之,解碼(Decode)/反序列化(deserialization)把從網(wǎng)絡(luò)、磁盤等讀取的字節(jié)數(shù)組還原成原始對(duì)象(通常是原始對(duì)象的拷貝),以方便后續(xù)的業(yè)務(wù)邏輯操作。
Netty預(yù)置的編解碼功能列表如下:base64、Protobuf、JBoss Marshalling、spdy等。
在GPS行業(yè)當(dāng)中,對(duì)于終端通信協(xié)議的設(shè)計(jì)有多種:
1)基于字符串設(shè)計(jì)的方式,這種方式就是終端發(fā)送一個(gè)ASCII字符串,然后服務(wù)器獲取后基于約定的分隔符分割為一個(gè)數(shù)組,再依次從數(shù)組中獲取對(duì)應(yīng)下標(biāo)的數(shù)據(jù),這種方式通常是深圳小的硬件公司的技術(shù)水平較低的開(kāi)發(fā)團(tuán)隊(duì)喜歡采用,這種方式容易理解,但傳輸字節(jié)較多,效率較低,比較占用流量,不適用于基于流量套餐的無(wú)線卡傳輸。
2)基于定長(zhǎng)協(xié)議的傳輸。
① 消息定長(zhǎng),例如每個(gè)報(bào)文的大小為固定長(zhǎng)度200字節(jié),如果不夠空位補(bǔ)空格。 ② 在包尾增加回車換行符進(jìn)行分割,例如FTP協(xié)議。
③ 將消息分為消息頭和消息體,消息頭中包含表示消息總長(zhǎng)度(或者消息體總體長(zhǎng)度) 的字段,通常涉及思路為消息頭的第一個(gè)字段使用init32來(lái)表示消息的總長(zhǎng)度。
④ 更復(fù)雜的應(yīng)用層協(xié)議,例如部標(biāo)808協(xié)議
部標(biāo)協(xié)議數(shù)據(jù)包設(shè)計(jì)的特點(diǎn):
1) 基于分隔符,包頭和包圍用0x7E來(lái)區(qū)分一個(gè)完整的數(shù)據(jù)包;
2) 動(dòng)態(tài)包頭,不想其他協(xié)議在設(shè)計(jì)的時(shí)候,包頭長(zhǎng)度都是固定長(zhǎng)度,而808協(xié)議的包頭長(zhǎng)度是不固定的;
3) 包體是動(dòng)態(tài)長(zhǎng)度,長(zhǎng)度從包頭中讀取。
解碼器就是要根據(jù)協(xié)議設(shè)計(jì)的數(shù)據(jù)包的規(guī)則,來(lái)對(duì)字節(jié)流進(jìn)行解析,解碼成完整的數(shù)據(jù)包。Netty提供了一下幾種基礎(chǔ)的解碼器提供給我們,供繼承或直接使用:
1)LineBasedFrameDecoder的工作原理是它依次便利ByteBuf中的可讀字節(jié),判斷看是否有“\n”或者“\r\n”,如果有就以此位置為結(jié)束位置,從可讀索引到結(jié)束位置區(qū)間的字節(jié)就組成了一行。他是以換行符為結(jié)束標(biāo)志的解碼器,支持?jǐn)y帶結(jié)束符或者不攜帶結(jié)束符兩種解碼方式,同時(shí)支持配置當(dāng)行的最大長(zhǎng)度。如果連續(xù)讀取帶最大長(zhǎng)度后任然沒(méi)有發(fā)現(xiàn)換行符,就會(huì)拋出異常,同時(shí)忽略掉之前讀到的異常碼流。
2)StringDecoder的功能非常簡(jiǎn)單,就是將接收到的對(duì)象轉(zhuǎn)換成字符串,然后繼續(xù)調(diào)用后面的handler。LineBasedFrameDecoder+StringDecoder組合就是按行切換的文本解碼器,它被設(shè)計(jì)用來(lái)支持TCP的粘包和拆包。
3)DelimiterBasedFrameDecoder特殊符號(hào)解碼器,其已經(jīng)過(guò)濾掉了分隔符。
4)FixedLengthFrameDecoder固定長(zhǎng)度解碼器,它能夠按照指定的長(zhǎng)度對(duì)消息進(jìn)行自動(dòng)解碼。利用FixedLengthFrameDecoder解碼器無(wú)論一次接受到多少數(shù)據(jù)報(bào),它都會(huì)按照構(gòu)造函數(shù)中設(shè)置的固定長(zhǎng)度進(jìn)行解碼,如果是半包消息,FixedLengthFrameDecoder會(huì)緩存半包消息并等待下個(gè)包到達(dá)后進(jìn)行拼包,直到取到一個(gè)完整的包。
4)基于Netty開(kāi)發(fā)一個(gè)部標(biāo)808協(xié)議的服務(wù)器,具體的步驟如下:
1)我們使用Netty要做的工作就是編寫(xiě)編碼器和解碼器,然后按照Netty的要求來(lái)編寫(xiě)調(diào)用,最后得到一個(gè)完整的808協(xié)議的數(shù)據(jù)包。
2)按照數(shù)據(jù)處理鏈條,分工職責(zé),為了提高終端接入能力和數(shù)據(jù)分析、入庫(kù)能力,將終端消息的處理分成獨(dú)立的五級(jí)處理模塊,每個(gè)處理模塊都是異步獨(dú)立的,每個(gè)模塊內(nèi)都含有獨(dú)立的處理隊(duì)列,互不影響,提高數(shù)據(jù)的吞吐量和系統(tǒng)的響應(yīng)能力。
1)第一級(jí):實(shí)時(shí)數(shù)據(jù)解析入庫(kù),入庫(kù)能力決定了客戶端所看到的實(shí)時(shí)數(shù)據(jù)是否延遲;
2)第二級(jí):報(bào)警分析并入庫(kù)(包括32種808協(xié)議規(guī)定的報(bào)警、停車報(bào)警和路線偏移報(bào)警),報(bào)警分析只有快速分析才能快速的推送到前端客戶端;
3) 第三級(jí):消息應(yīng)答和指令下發(fā),應(yīng)答可以有一定的延遲,而不影響整個(gè)系統(tǒng)性能。
4)第四級(jí):報(bào)表統(tǒng)計(jì),由于油量統(tǒng)計(jì)、里程統(tǒng)計(jì)、上線率統(tǒng)計(jì),需要定時(shí)掃描數(shù)據(jù)庫(kù),生成每個(gè)時(shí)段的數(shù)據(jù)統(tǒng)計(jì)提供給報(bào)表查詢使用.
5)第五級(jí):日志記錄和顯示
由于netty和Mina都能非常好的和spring容器集成在一起,引入spring框架,基于面向接口編程,系統(tǒng)可以同時(shí)支持netty和mina兩種通信框架,用戶可以根據(jù)自己的環(huán)境,通過(guò)配置決定是用mina或者是netty。
5)連接管理和日志報(bào)文監(jiān)控
在windows系統(tǒng),可以運(yùn)行swing界面進(jìn)行監(jiān)控,如果運(yùn)行在阿里云的linux系統(tǒng)上,可以直接編寫(xiě)java shell腳本,基于后臺(tái)服務(wù)運(yùn)行,通過(guò)java 命令來(lái)調(diào)用當(dāng)前的連接,日志監(jiān)控,主要依賴于log文件。
jt808服務(wù)器代碼都是經(jīng)過(guò)眾多客戶使用檢驗(yàn)過(guò)的千錘百煉的成熟的版本,協(xié)議解析、命令下發(fā)、報(bào)警解析、數(shù)據(jù)庫(kù)入庫(kù)、數(shù)據(jù)統(tǒng)計(jì)、壓力測(cè)試等各方面都考慮的非常充分完善,808協(xié)議全協(xié)議棧的實(shí)現(xiàn),拿到手后,直接就可以使用了,帶有庫(kù)表文檔和字段說(shuō)明。
需要JT 808 源碼(java和C#兩版本可選其一)+808模擬測(cè)試終端工具 +壓力測(cè)試工具 的請(qǐng)聯(lián)系我購(gòu)買1200元(2379423771@qq.com), Java Mina框架版本參見(jiàn):基于Java Mina框架的部標(biāo)GPS服務(wù)器
808服務(wù)器主要用的庫(kù)表:
部門表 |
車輛表 |
終端表 |
實(shí)時(shí)表 |
歷史軌跡表 |
駕駛員表 |
電子運(yùn)單表 |
報(bào)警統(tǒng)計(jì)報(bào)表 |
報(bào)警推送表 |
電子圍欄表 |
線段表 |
終端命令表 |
終端參數(shù)表 |
基礎(chǔ)數(shù)據(jù)表 |
多媒體上傳記錄 |
行駛記錄儀表 |
里程統(tǒng)計(jì)中間表 |
部門上線率統(tǒng)計(jì)表 |
油量變化記錄 |
油量和里程統(tǒng)計(jì)表 |
車輛上線率統(tǒng)計(jì)表 |
五分鐘一次油量和里程記錄 |
6) 本808服務(wù)器對(duì)于部標(biāo)808全部協(xié)議棧都進(jìn)行了充分的支持:
序號(hào) | 項(xiàng)目名稱 | 觸發(fā)條件 | 預(yù)期回應(yīng) |
01 | 終端心跳 | 根據(jù)設(shè)定的心跳時(shí)間參數(shù),定時(shí)自動(dòng)上報(bào) | 主動(dòng)上發(fā),需要平臺(tái)提供通用應(yīng)答,長(zhǎng)時(shí)間無(wú)法獲得應(yīng)答將導(dǎo)致程序自動(dòng)斷開(kāi)重連。 |
02 | 設(shè)置終端參數(shù) | 平臺(tái)下發(fā) | 回復(fù)通用應(yīng)答,可設(shè)置的參數(shù)參考行標(biāo)協(xié)議文本8.8 |
03 | 超速設(shè)置 | 平臺(tái)下發(fā) | 回復(fù)通用應(yīng)答 |
04 | 疲勞駕駛設(shè)置 | 平臺(tái)下發(fā) | 回復(fù)通用應(yīng)答 |
05 | 超時(shí)停車設(shè)置 | 平臺(tái)下發(fā) | 回復(fù)通用應(yīng)答 |
06 | 查詢終端參數(shù) | 平臺(tái)下發(fā) | 回復(fù)0×0104應(yīng)答參照行標(biāo)協(xié)議文本8.10描述,回復(fù)的參數(shù)信息包含前述設(shè)置指令所設(shè)定修改的內(nèi)容 |
07 | 終端控制 | 平臺(tái)下發(fā) | 回復(fù)通用應(yīng)答 |
08 | 位置信息查詢 | 平臺(tái)下發(fā) | 回復(fù)固化的位置信息:26.033435N,119.139317E 高度23.59,速度0,角度0 |
09 | 臨時(shí)位置跟蹤控制 | 平臺(tái)下發(fā) | 回復(fù)通用應(yīng)答 |
10 | 文本信息下發(fā) | 平臺(tái)下發(fā) | 回復(fù)通用應(yīng)答 |
11 | 追加事件 | 平臺(tái)下發(fā) | 回復(fù)通用應(yīng)答 |
12 | 刪除特定事件 | 平臺(tái)下發(fā) | 回復(fù)通用應(yīng)答 |
13 | 更新事件 | 平臺(tái)下發(fā) | 回復(fù)通用應(yīng)答 |
14 | 修改事件 | 平臺(tái)下發(fā) | 回復(fù)通用應(yīng)答 |
15 | 刪除全部事件 | 平臺(tái)下發(fā) | 回復(fù)通用應(yīng)答 |
16 | 追加新事件 | 平臺(tái)下發(fā) | 回復(fù)通用應(yīng)答 |
17 | 提問(wèn)下發(fā) | 平臺(tái)下發(fā) | 程序立即回復(fù)通用應(yīng)答,稍后由用戶手動(dòng)操作回復(fù)提問(wèn) |
18 | 信息點(diǎn)播菜單追加 | 平臺(tái)下發(fā) | 回復(fù)通用應(yīng)答 |
19 | 信息點(diǎn)播菜單修改 | 平臺(tái)下發(fā) | 回復(fù)通用應(yīng)答 |
20 | 信息點(diǎn)播菜單更新 | 平臺(tái)下發(fā) | 回復(fù)通用應(yīng)答 |
21 | 信息點(diǎn)播菜單刪除 | 平臺(tái)下發(fā) | 回復(fù)通用應(yīng)答 |
22 | 信息點(diǎn)播菜單追加 | 平臺(tái)下發(fā) | 回復(fù)通用應(yīng)答 |
23 | 信息點(diǎn)播菜單修改 | 平臺(tái)下發(fā) | 回復(fù)通用應(yīng)答 |
24 | 信息點(diǎn)播菜單更新 | 平臺(tái)下發(fā) | 回復(fù)通用應(yīng)答 |
25 | 信息服務(wù) | 平臺(tái)下發(fā) | 回復(fù)通用應(yīng)答 |
26 | 電話回?fù)?/p> | 平臺(tái)下發(fā) | 回復(fù)通用應(yīng)答,不觸發(fā)任何邏輯動(dòng)作,請(qǐng)關(guān)注日志 |
27 | 電話回?fù)躝監(jiān)聽(tīng) | 平臺(tái)下發(fā) | 回復(fù)通用應(yīng)答,不觸發(fā)任何邏輯動(dòng)作,請(qǐng)關(guān)注日志 |
28 | 設(shè)置電話本_刪除 | 平臺(tái)下發(fā) | 回復(fù)通用應(yīng)答 |
29 | 設(shè)置電話本_更新電話本 | 平臺(tái)下發(fā) | 回復(fù)通用應(yīng)答 |
30 | 設(shè)置電話本_追加電話本 | 平臺(tái)下發(fā) | 回復(fù)通用應(yīng)答 |
31 | 設(shè)置電話本_修改電話本 | 平臺(tái)下發(fā) | 回復(fù)通用應(yīng)答 |
32 | 車輛控制_車門解鎖 | 平臺(tái)下發(fā) | 回復(fù)通用應(yīng)答 |
33 | 車輛控制_車門加鎖 | 平臺(tái)下發(fā) | 回復(fù)通用應(yīng)答 |
34 | 更新圓形區(qū)域 | 平臺(tái)下發(fā) | 回復(fù)通用應(yīng)答 |
35 | 刪除圓形區(qū)域 | 平臺(tái)下發(fā) | 回復(fù)通用應(yīng)答 |
36 | 更新矩形區(qū)域 | 平臺(tái)下發(fā) | 回復(fù)通用應(yīng)答 |
37 | 刪除矩形區(qū)域 | 平臺(tái)下發(fā) | 回復(fù)通用應(yīng)答 |
38 | 更新多邊形區(qū)域 | 平臺(tái)下發(fā) | 回復(fù)通用應(yīng)答 |
39 | 刪除多邊形區(qū)域 | 平臺(tái)下發(fā) | 回復(fù)通用應(yīng)答 |
40 | 更新路線 | 平臺(tái)下發(fā) | 回復(fù)通用應(yīng)答 |
41 | 刪除所有路線 | 平臺(tái)下發(fā) | 回復(fù)通用應(yīng)答 |
42 | 行駛記錄儀數(shù)據(jù)采集命令 | 平臺(tái)下發(fā) | 根據(jù)形式記錄議命令字發(fā)回測(cè)試數(shù)據(jù),數(shù)據(jù)可能會(huì)產(chǎn)生分包 |
43 | 行駛記錄儀參數(shù)下傳命令 | 平臺(tái)下發(fā) | 回復(fù)通用應(yīng)答 |
44 | 抓拍立即上傳 | 平臺(tái)下發(fā) | 回復(fù)通用應(yīng)答,隨后分包上發(fā)固化的多媒體數(shù)據(jù),上發(fā)數(shù)據(jù)與多媒體通道有關(guān)* |
45 | 錄像立即上傳 | 平臺(tái)下發(fā)抓拍指令附帶錄像提示 | 回復(fù)通用應(yīng)答,隨后分包上發(fā)固化的多媒體數(shù)據(jù),上發(fā)數(shù)據(jù)與多媒體通道有關(guān)* |
46 | 檢索多媒體列表 | 平臺(tái)下發(fā) | 根據(jù)查詢的多媒體類型回復(fù)固化的多媒體列表數(shù)據(jù),參考行標(biāo)協(xié)議8.46,通道與時(shí)間參數(shù)將被解析于日志中,但是不會(huì)影響列表內(nèi)容 |
47 | 存儲(chǔ)多媒體上傳 | 平臺(tái)下發(fā) | 根據(jù)通道*和多媒體類型定義回傳多媒體數(shù)據(jù),時(shí)間和事件等參數(shù)將被正確解析與日志中,但是不會(huì)影響上發(fā)的多媒體內(nèi)容 |
48 | 錄音32Kbps立即上傳 | 平臺(tái)下發(fā) | 回復(fù)通用應(yīng)答 |
49 | 數(shù)據(jù)下行透?jìng)?/p> | 平臺(tái)下發(fā) | 回復(fù)通用應(yīng)答 |
50 | 平臺(tái)RSA公鑰 | 平臺(tái)下發(fā) | 回復(fù)終端RSA公鑰,本軟件將把平臺(tái)下發(fā)的RSA公鑰回發(fā)以驗(yàn)證協(xié)議的正確性 |
posted on 2017-04-16 08:35 Speed 閱讀(4916) 評(píng)論(0) 編輯 收藏 所屬分類: jt808協(xié)議和java技術(shù)