2016-08-03-信息系統實踐手記8-兩模塊通信的一些事


layout: post
title: 2016-08-03-信息系統實踐手記8-兩模塊通信的一些事
key: 20160803
tags: 對接 卡口 黑名單 佈防 撤防 訂閱 取消 設備 列表 模型
modify_date: 2016-08-03
---html

信息系統實踐手記8-兩模塊通信的一些事

說明:java

正文:git

  • 信息系統實踐手記系列是系筆者在平時研發中前後遇到的大小的問題,其中比較典型的內容加以收集和分享。
  • 信息系統實踐手記目錄:博客園(或查看源碼的README.MD文件)

摘要:github

  • 此文描述了兩個模塊通訊方面的內容。

正文web

在信息系統開發和對接的過程當中,免不了要遇到兩個模塊之間的消息互通,即使都是本身開發的2個模塊互通,或者本身模塊和第三方某個模塊通信。
這裏儘可能不涉及具體技術(這個你們本身找資料看書),主要是掰扯一下會涉及到的一些思考和狀況。

1. 對接協議的2個層次:

  • 兩個代碼實體(簡稱模塊)互相須要通信,每每在不一樣的主機(PC/IP)上,也偶有在同一個主機上的,TCP/IP協議已經屏蔽了物理機的差別,經過IP/PORT來區分資源,區分模塊或功能對等實體。回過來,2個模塊要通信,2端代碼要交互信息(數據/消息/信令/碼流/結構/隨便怎麼稱呼),參照目前互聯網的TCP/IP協議或其餘奇怪協議,基本分爲兩種層次:
    • A:物理實現層(對於TCP/IP中的物理層,鏈路層等)的比特流,二進制,高低電平,網卡,網絡設備等支持這個協議。好比3伏特/12伏特表示0或1等等,這是電氣特性;可靠性依賴於硬件的工做特性,電氣特性,以及糾錯手段(一些數學和工程方法)。
    • B:高層(統一叫高層,就是這個意思),基於二進制bit層次上的有含義的層次,字節流層次,byte(通常是8bit=1byte),而byte就對應了byte編碼規範,好比ASCII或UTF-8,這樣一串bytes就有邏輯含義了(26個英文字母及大小寫,天然數10個數字,特殊符號,回車換行,加減乘除符號,不可見符號等等);其實網絡上傳遞的都是字節流,而TCP/IP協議主要也是處理這個字節流從端到端的傳送;可靠性依賴於下層A的bit流,並也能夠增長適當的校驗CRC等各類手段(也是一些數學方法)
  • 因此雖然ISO/OSI的7層網絡模型設計的很好,其實落實到實際實現的TCP/IP協議,也就主要分爲以上A/B兩個層次,A中還細分幾個,B中也有細分但用的很少;主要理解這2個層次,從物理bit的可靠傳輸,架構其有邏輯含義的高層字節byte傳輸,這麼個概念。後續主要就談B層了,畢竟A層次目前已經穩定,除非量子力學顛覆當前的計算機原型(節點PC),而後天然而然的可能顛覆網絡基礎物理層A的電氣特性,搞些先進的,這個咱們就不談了,還有5到10年就撲面而來了。

這裏只談B層;算法

2. TCP/IP協議主要分爲TCP/UDP2種:

  • TCP/IP協議分爲主要的2種,UDP/TCP:
    • TCP:面向鏈接(在網絡基礎層A上維護的邏輯上的鏈接通道) 的有狀態的字節流通信,保證數據包的按序及正確傳送,有狀態,因此能錯誤重傳,並維護鏈接通道;但數據報的緩存及發送依賴於「邏輯鏈接通道」兩端模塊程序(每每是OS的網絡驅動,網卡的驅動程序等)自主決定。因此會產生粘包及粘包如何分割的問題,這是TCP經典問題,請另查資料(或看netty官網的userguide入門章節,有比較簡單經典的描述);
      • 場景:須要可靠鏈接,直接拿來用的場景,犧牲必定的效率;用的較普遍;
    • UDP:無鏈接,不保證數據包按照發送順序到達目的地,甚至不保證能到達目的地;它其實容許2端模塊本身經過高層協議來組織,數據包的順序檢查,丟包重傳,及狀態流轉等;等於本身實現一個小小的簡單TCP;
      • 場景: 網絡環境表穩定可靠,對數據正確性及順序無特別嚴格要求,效率較高;好比局域網播放視頻等;
    • 說明:隨着網絡硬件性能,模塊所在節點PC或服務器的性能提高,也許你們以爲即便看視頻也用TCP來的更方便和效果好,那也是能夠的,這無一個定論,看具體狀況和項目方案的需求和實施狀況而定

4. 針對TCP的幾種使用方法

  • TCP比較好用,可是有個特色就是粘包。雖然它是面向鏈接,有狀態維護管理,丟包重傳,且保證次序。可是兩端節點上的莊模塊的網絡驅動底層庫,各自有算法,緩存cache和策略,效率,切分包的大小(MTU)等都不一樣,致使接收方獲得的包只在總體字節流bytes上是一致的,但沒法知道發送方每次send給底層的byte字節是如何劃分的。這就是經典的粘包及切分問題;通常有以下幾個方法來處理;
    • 方法1:定長字段法;
      • 這樣就不怕粘包了,發送端只管發,接收端從接受緩存不斷輪詢,若是滿了必定長度length後,就讀入;這裏固然假設TCP是有序,丟包會重傳的。
      • 優勢:實現簡單;邏輯也簡單;
      • 缺點:一旦TCP傳輸有錯(網絡很差,機率偶發,協議棧缺陷等,總會錯誤),則總體就會偏移,數據錯位就會錯誤;
      • 改進:根據其缺點,可在定長中增長特殊頭標記,好比定長length=64bytes,其中開始標記flag=\x0C等,當知足二者,就解碼爲邏輯內容,內容正確就用,內容錯誤就丟棄,並找到下一個有效的定長數據片(且以flag開頭);這其實已經有一點TLV的雛形了。
    • 方法2:分隔符方式(變長字段法);
      • 和定長字段法相對的,就是經過一個分隔符來區分先後兩端內容,則沒斷長度可變化,分隔符不可重複,一樣能解決粘包問題;
      • 優勢:實現簡單,邏輯較簡單,比較可靠;
      • 缺點:要保證分隔符是payload(有效載荷,即實際負載和傳輸的數據)中不能包含的!並且算法效率低下,須要每一個byte都檢查是否爲分隔符;
      • 改進:若是能配合定長的數據片,那其實等價於加一個flag頭。
    • 方法3:TLV方式(經典高效):
      • TLV是比較經典的方式,用的相對較多。TLV(通常指Type-Length-Value)。它的協議通常會約定一個head頭結構,包含flag和length,flag用來找到TLV的頭(是個標記字節,沒必要惟一,但不能不少),找到flag後,就根據協議約定解析head頭結構,解析失敗則繼續查找flag;解析成功後,就能得到head+body的總體長度length,從而解析獲得body的數據;在body中經過一組組不定長的(length-value)結構,一個長度一個value值來承載payload,但length字段的自身長度是固定的,通常爲1都4個字節之間,看TLV總體的協議定義;body的length和head的中length的自身長度也沒必要要必定一致。另外,這個type是類型的含義,是TLV協議手冊的約定,通常會說明有K組<length,value>,每組是int,long,double,bytes[],等等;
      • 優勢:高效的經過length字段獲取value,不用每一個字節都檢查;且支持不一樣的數據結構;
      • 缺點:實現比較複雜,兩邊TLV協議手冊顯然比前2種方法的描述要詳細;
      • 改進:能夠經過諸如JAVA的反射或其餘方法,來將TLV協議經過「配置文件」的方式,讓程序自動根據清晰明瞭容易維護的配置文件來生成編解碼程序(CODEC)。

4. 針對TCP心跳的一些說明

TCP協議內容較多,有好幾本大書,但核心內容,網上也轉載不少,這裏只提一些內容。
TCP若是不在初始化socket的時候給予超時timeout設定(看tcp類庫支持哪些超時,通常如java io/NIO支持鏈接超時,傳輸超時等),那麼默認就是2小時(120分鐘),在120分鐘內TCP協議內部本身有心跳維持socket鏈接通道,
超過120分鐘,則按照狀態機變化,兩端都開始拆除TCP鏈接。固然,兩端莊模塊開發的若是很差,這就會致使對端有大量端口TIME_WAIT等等TCP狀態機不能順利,快速,高效的拆除並被複用,致使資源消耗,甚至耗光65535個port口。
除了TCP自身的超時,或者網絡lib庫能力範圍內給予的鏈接超時,傳輸超時(閒置idle超時)外,樁模塊能夠人爲的在邏輯層添加本身的超時和心跳機制。舉例以下:
(1)收到PING,就發PONG,收到PONG,不響應;這是對等心跳探測包,有發起者探測對方是否活着alive;
(2)兩邊約定心跳間隔時間,好比每120秒發送心跳包(好比「HB」2個字符,或某種字節等),或者約定只有server發給client,不用反向;
特別說明:這是高層邏輯的心跳,應用層本身使用的,並且其實現根據前述3種使用方法而不一樣,好比你用TLV,那麼也須要額外定義一個「心跳包」的協議;

5. 用哪些類庫?

通常開發樁模塊的時候,兩端約定好傳輸協議,好比TLV,那麼就各自開發。你用熟悉的語言好比java,並且會進一步使用現成的框架,好比netty(異步io框架),
這樣你就不用赤裸的使用java的nio本身一步步處理,不用重複發明輪子。netty是一個很是好用的庫,開發者同時也開發了mina,兩個庫有點相似,各有千秋和側重。
詳見我整理的[ITIS-資料集合貼]中的介紹和電子書;

6. 對接協議的的安全性問題

TCP是有鏈接,有狀態,有序,丟包重傳的,因此他有基礎的正確性保證。但TCP徹底會受到重傳攻擊,或偵聽竊聽,或篡改數據包等破壞方式。並且TCP保證的是網絡層的字節流的按序正確到達,不保證上層邏輯(應用層)認爲的數據是百分百正確的。因此,有以下建議:
(1)能夠根據需求,對本身的數據進行編碼,壓縮,加密;
(2)能夠參考一些開源的密鑰,加密算法,認證,證書等協議的使用;
(3)曾經這樣弄過,給payload轉爲base64,而且作了MD5摘要,傳到對端MD5用來驗證數據對不對,也可做爲異步反饋的key值。

總結,老是TCP協議豐富多彩,若是熟悉一些框架和經常使用手段,再加上一些諸如MD5,加密壓縮算法等,徹底能夠本身搭建和實現不一樣的傳輸協議,知足不一樣狀況的要求,在兩個對端樁模塊之間實現數據的傳遞。緩存

END

相關文章
相關標籤/搜索