MM2協議簡介

mgoann發表於2020-04-06

MM2協議簡介

MM2協議簡介

MM2協議採用TCP協議承載,二進位制編碼格式。除握手訊息和心跳訊息外,其它訊息結構分為MM2協議頭部和業務訊息體兩部分。

 

1MM2訊息頭定義為定長欄位,欄位定義固定總長度為(28個位元組)。包括:

Length:訊息總長度(4個位元組)

MessageType:訊息型別(4個位元組)

SourceModuleType:源模組型別(2個位元組)

SourceModuleID:源模組ID(2個位元組)

SourceManagerType:源Manager型別(2個位元組)

SourceManagerID:源ManagerID(2個位元組)

TargetModuleType:目的模組型別(2個位元組)

TargetModuleID:目的模組ID(2個位元組)

TargetManagerType:目的ManagerType(2個位元組)

TargetManagerID:目的ManagerID(2個位元組)

SequenceID:由傳送方填寫,請求和響應訊息必須保持一致(4個位元組)

 

2MM2訊息體定義:

資料型別 是否是必填資料 編碼方式 說明

定長資料 直接將資料內容寫入訊息體

定長資料 可選欄位 可選標識+資料內容(如果內容存在) 可選欄位為1BYTE0標識不存在,1標識存在,後面跟資料內容。

變長資料 長度+資料內容 長度為4個位元組

變長資料 可選欄位 可選標識+長度+資料內容

上表中的’+’在實際碼流中不存在,僅表示順序關係。

 

3、通訊過程:

MM2協議採用TCP協議承載,支援TCP長連線,不支援TCP短連線。

首先客戶端向伺服器端發起TCP連線請求建立TCP連線。

 TCP連線建立後,客戶端向伺服器端傳送握手請求訊息。握手請求訊息中包含有客戶端的能力資訊,伺服器端如果允許客戶端握手,則返回握手成功響應訊息,握手成功響應訊息中包含伺服器的能力資訊。如果握手失敗,則伺服器返回握手失敗響應。重連間隔時間預設為5秒,可修改。

 MM2連線建立成功之後,雙方需要互相傳送心跳訊息維持連線。心跳訊息沒有響應。對於任何一方,如果發現在一段時間內沒有收到對端傳送過來的任何資料(注意:包括心跳訊息、業務訊息等任何訊息)則主動斷開連線,並嘗試重連。心跳超時時間應設定大於對端的心跳傳送間隔時間。預設設定:心跳間隔時間=2秒,心跳超時時間=心跳間隔時間*2

 

MM2協議特點

 

1.       高效

主要體現為:

(1) 長連線

由於Socket連線的建立和關閉很耗效能,所以MM2只建立一次連線,並把連線一致保持著。所謂的多路複用。

缺點:容易出現斷連,

可以通過 netstat na | grep (portId)

命令來判斷是否連線(有3種狀態:LISTEN(監聽)ESTABLISHED(連線)TIME_WAIT(等待)

(2) 約定大於配置

如模組雙方通訊,一方按照某一順序封裝傳送訊息,另一方則必須嚴格按照這個順序進行讀取。可以從MM2協議裡看出MM2並沒有將基本欄位型別和結構體一些附加資訊寫入傳輸流中,都是通過約束來完成,這樣達到了節省了傳輸負載,提供效能。

缺點:缺乏靈活性,易出去介面不同步。

可通過tcpdump i lo tcp port (portId) Xo 10000 vv

命令抓包進行問題的確認。

(3) 二進位制傳輸

優點:節省流量,效能提高了。

 

2. 安全

(1) 心跳訊息

心跳訊息無需響應,由連著的雙方互發訊息。

(2) 握手訊息

在建立Socket連線的時候,傳送握手訊息,進行身份的確認,確認成功才會進行後續的操作。

握手訊息由客戶端發起,服務端返回相應的響應訊息。

 

3.  異構性

MM2協議中只規定了基本型別如何表示,所以不同程式語言實現的模組可以通過MM2協議來互動。

 

4. 支援各種編解碼

 

5. 支援集合、陣列、自定義結構體。

其中集合和資料是通過一個特殊的4位元組標識來表示。

 

MM2java序列化的效能比較

 

1MM2java序列化的效能比較

   示例程式碼:

      //序列化物件

        TestSerializable ts = new TestSerializable("1001","zhangshun");

        long time = System.currentTimeMillis();

        ByteArrayOutputStream baos = new ByteArrayOutputStream();;

        ObjectOutputStream oos = null;

        for (int i = 0; i < 100000; i++)

        {

            try

            {

                oos = new ObjectOutputStream(baos);

                oos.writeObject(ts);

            }

            catch (IOException e)

            {

                e.printStackTrace();

            }

        }

        System.out.println("serialize length="+baos.toByteArray().length/(1024*1024) +" M");

        System.out.println("serialize used time:" + (System.currentTimeMillis() - time) +"ms");

       

        time = System.currentTimeMillis();

        //MM2編碼封裝物件

        TestMM2 tmm = new TestMM2("1001","zhangshun");

        long mmLength = 0;

        for (int i = 0; i < 100000; i++)

        {

            byte[] bb = tmm.toByte();

            mmLength += bb.length + 28; //28MM2頭長度

        }

        System.out.println("mm2 length = " + mmLength/(1024*1024) + " M");

        System.out.println("mm2 used time:" + (System.currentTimeMillis() - time) +"ms");

 

執行結果:

serialize length=9 M

serialize used time:1875ms

mm2 length = 4 M

mm2 used time:375ms

從中可以看出MM2效能無論是從時間還是空間都要優於java序列化.

相關文章