基於Java Netty框架構建高性能的部標808協議的GPS服務器

使用Java語言開發一個高質量和高性能的jt808 協議的GPS通訊服務器,並非一件簡單容易的事情,開發出來一段程序和可以承受數十萬臺車載接入是兩碼事,除去開發部標808協議的固有複雜性和幾個月長週期的協議Bug調試,做爲大批量794車載終端接入的服務端,須要可以處理網絡的閃斷、客戶端的重連、安全認證和消息的編解碼、半包處理等。若是沒有足夠的網絡編程經驗積累和深刻了解部標808協議文檔,自研的GPS服務器每每須要半年甚至數年的時間才能最終穩定下來,這種成本即使對一個大公司而言也是個嚴重的挑戰。

1)咱們在開發部標協議的GPS服務器,須要解決如下幾個問題:前端

1.      通訊服務器固有的鏈接管理,可以處理網絡的閃斷、客戶端的重連、安全認證和消息的編解碼、半包處理;java

2.      海量終端接入的高併發性能;linux

3.      良好的內存管理,車載終端的鏈接本事是基於GPRS的無線鏈接,車輛在野外高速移動過程當中,信號處於不穩定狀態,雖然是基於長鏈接,可是這種鏈接不斷的中斷和接入,服務器在處理終端接入,數據解析,報警分析,批量入庫的時候,可以內存分配合理,不會形成內存泄漏,在百萬次的調用中不會形成內存累計上升;spring

 

2)要開發一個高性能的GPS服務器的三個主題:shell

1) 傳輸:用什麼樣的通道將數據發送給對方,BIO、NIO或者AIO,IO模型在很大程度上決定了框架的性能。 數據庫

2) 協議:採用什麼樣的通訊協議,HTTP或者內部私有協議。協議的選擇不一樣,性能模型也不一樣。相比於公有協議,內部私有協議的性能一般能夠被設計的更優。 編程

3) 線程:數據報如何讀取?讀取以後的編解碼在哪一個線程進行,編解碼後的消息如何派發,Reactor線程模型的不一樣,對性能的影響也很是大。windows

Netty是業界最流行的NIO框架,能夠很好的解決上面三個問題,它的可靠性、高性能和可擴展性已經獲得了上百上千的商用項目驗證,相對於.NET中的基於完成端口的通訊框架,它要優越的多,它的優勢總結以下:數組

1.      API使用簡單,開發門檻低;緩存

2.      功能強大,內聚了不少實用的功能,簡化用戶的開發;

3.      定製性好,經過ChannelPipeline機制能夠靈活的進行功能定製和擴展;

4.      性能高;

5.      成熟穩定,社區活躍,Bug的修復週期比較短,新功能不斷的被加入,用戶能夠體驗到更多、更實用的功能。

6.      經歷了大規模不一樣行業的商用考驗,架構質量獲得了充分的驗證。

Netty爲了向使用者屏蔽NIO通訊的底層細節,在和用戶交互的邊界作了封裝,目的就是爲了減小用戶開發工做量,下降開發難度。ServerBootstrap是Socket服務端的啓動輔助類,用戶經過ServerBootstrap能夠方便的建立Netty的服務端。

3)編碼器和解碼器的設計

對於808協議的解析處理,須要編寫自定義的解碼器了,目前Netty提供了多個基礎編碼器能夠供開發者進行繼承和拓展,開發的時候,須要瞭解這幾個解碼器的主要做用,主要用於那些通訊數據傳輸的場景。

爲了下降用戶的開發難度,Netty對經常使用的功能和API作了裝飾,以屏蔽底層的實現細節。編解碼功能的定製,對於熟悉Netty底層實現的開發者而言,直接基於ChannelHandler擴展開發,難度並非很大。可是對於大多數初學者或者不肯意去了解底層實現細節的用戶,須要提供給他們更簡單的類庫和API,而不是ChannelHandler。

Netty在這方面作得很是出色,針對編解碼功能,它既提供了通用的編解碼框架供用戶擴展,又提供了經常使用的編解碼類庫供用戶直接使用。在保證定製擴展性的基礎之上,儘可能下降用戶的開發工做量和開發門檻,提高開發效率。

一般咱們也習慣將編碼(Encode)稱爲序列化(serialization),它將對象序列化爲字節數組,用於網絡傳輸、數據持久化或者其它用途。

反之,解碼(Decode)/反序列化(deserialization)把從網絡、磁盤等讀取的字節數組還原成原始對象(一般是原始對象的拷貝),以方便後續的業務邏輯操做。

Netty預置的編解碼功能列表以下:base6四、Protobuf、JBoss Marshalling、spdy等。

在GPS行業當中,對於終端通訊協議的設計有多種:

1)基於字符串設計的方式,這種方式就是終端發送一個ASCII字符串,而後服務器獲取後基於約定的分隔符分割爲一個數組,再依次從數組中獲取對應下標的數據,這種方式一般是深圳小的硬件公司的技術水平較低的開發團隊喜歡採用,這種方式容易理解,但傳輸字節較多,效率較低,比較佔用流量,不適用於基於流量套餐的無線卡傳輸。

2)基於定長協議的傳輸。

① 消息定長,例如每一個報文的大小爲固定長度200字節,若是不夠空位補空格。 ② 在包尾增長回車換行符進行分割,例如FTP協議。

③ 將消息分爲消息頭和消息體,消息頭中包含表示消息總長度(或者消息體整體長度) 的字段,一般涉及思路爲消息頭的第一個字段使用init32來表示消息的總長度。

④ 更復雜的應用層協議,例如部標808協議

部標協議數據包設計的特色:

1) 基於分隔符,包頭和包圍用0x7E來區分一個完整的數據包;

2) 動態包頭,不想其餘協議在設計的時候,包頭長度都是固定長度,而808協議的包頭長度是不固定的;

3) 包體是動態長度,長度從包頭中讀取。

 解碼器就是要根據協議設計的數據包的規則,來對字節流進行解析,解碼成完整的數據包。Netty提供了一下幾種基礎的解碼器提供給咱們,供繼承或直接使用:

1)LineBasedFrameDecoder的工做原理是它依次便利ByteBuf中的可讀字節,判斷看是否有「\n」或者「\r\n」,若是有就以此位置爲結束位置,從可讀索引到結束位置區間的字節就組成了一行。他是以換行符爲結束標誌的解碼器,支持攜帶結束符或者不攜帶結束符兩種解碼方式,同時支持配置當行的最大長度。若是連續讀取帶最大長度後任然沒有發現換行符,就會拋出異常,同時忽略掉以前讀到的異常碼流。

2)StringDecoder的功能很是簡單,就是將接收到的對象轉換成字符串,而後繼續調用後面的handler。LineBasedFrameDecoder+StringDecoder組合就是按行切換的文本解碼器,它被設計用來支持TCP的粘包和拆包。

3)DelimiterBasedFrameDecoder特殊符號解碼器,其已通過濾掉了分隔符。

4)FixedLengthFrameDecoder固定長度解碼器,它可以按照指定的長度對消息進行自動解碼。利用FixedLengthFrameDecoder解碼器不管一次接受到多少數據報,它都會按照構造函數中設置的固定長度進行解碼,若是是半包消息,FixedLengthFrameDecoder會緩存半包消息並等待下個包到達後進行拼包,直到取到一個完整的包。

4)基於Netty開發一個部標808協議的服務器,具體的步驟以下:

1)咱們使用Netty要作的工做就是編寫編碼器和解碼器,而後按照Netty的要求來編寫調用,最後獲得一個完整的808協議的數據包。

2)按照數據處理鏈條,分工職責,爲了提升終端接入能力和數據分析、入庫能力,將終端消息的處理分紅獨立的五級處理模塊,每一個處理模塊都是異步獨立的,每一個模塊內都含有獨立的處理隊列,互不影響,提升數據的吞吐量和系統的響應能力。

1)第一級:實時數據解析入庫,入庫能力決定了客戶端所看到的實時數據是否延遲;

2)第二級:報警分析併入庫(包括32種808協議規定的報警、停車報警和路線偏移報警),報警分析只有快速分析才能快速的推送到前端客戶端;

3)  第三級:消息應答和指令下發,應答能夠有必定的延遲,而不影響整個系統性能。

4)第四級:報表統計,因爲油量統計、里程統計、上線率統計,須要定時掃描數據庫,生成每一個時段的數據統計提供給報表查詢使用.

5)第五級:日誌記錄和顯示

因爲netty和Mina都能很是好的和spring容器集成在一塊兒,引入spring框架,基於面向接口編程,系統能夠同時支持netty和mina兩種通訊框架,用戶能夠根據本身的環境,經過配置決定是用mina或者是netty。

5)鏈接管理和日誌報文監控

在windows系統,能夠運行swing界面進行監控,若是運行在阿里雲的linux系統上,能夠直接編寫java shell腳本,基於後臺服務運行,經過java 命令來調用當前的鏈接,日誌監控,主要依賴於log文件。

jt808服務器代碼都是通過衆多客戶使用檢驗過的千錘百煉的成熟的版本,協議解析、命令下發、報警解析、數據庫入庫、數據統計、壓力測試等各方面都考慮的很是充分完善,808協議全協議棧的實現,拿到手後,直接就可使用了,帶有庫表文檔和字段說明。

技術交流 By 省厓 QQ:2252224326  2252224326@qq.com 版權全部 http://blog.sina.com.cn/u/6029512413

相關文章
相關標籤/搜索