Netty 通訊協(xié)議設計概要
1. 前言
上節(jié)內容,我們主要介紹了 Netty 的粘包和拆包問題,并且大致介紹了 Netty 提供的常見拆包器,分別是固定長度拆包器、行拆包器、分隔符拆包器、基于長度域拆包器,但是它們只是相對簡單的協(xié)議,也就是說無法滿足復雜的業(yè)務場景,因此,我們可以通過自定義協(xié)議的方式去解決 TCP 的粘包和拆包問題。
2. 了解什么是協(xié)議
首先,我們大概了解什么是協(xié)議,協(xié)議可以把它認為是一種規(guī)則而不是技術,約束客戶端和服務端之間通訊,數(shù)據(jù)組裝和拆分的一種規(guī)范。客戶端安裝某種規(guī)范去組裝數(shù)據(jù),把數(shù)據(jù)傳輸給服務端,服務端再安裝這種規(guī)范拆解數(shù)據(jù),那么這就是一種協(xié)議,可以根據(jù)實際業(yè)務區(qū)指定符合自身的協(xié)議,其實基于 Netty 去制定的私有協(xié)議,我個人接觸過的是傳輸車輛 GPS 數(shù)據(jù)的 809 協(xié)議,在和 GPS 服務器通訊時,必須按照該協(xié)議去進行封裝和解析數(shù)據(jù),否則通訊異常。
其實,類似的規(guī)則還有很多,從開發(fā)的角度來說,都是各種規(guī)則和約束,比如說:前面提到的序列化技術,序列化其實就是把數(shù)據(jù)按照某種規(guī)則去轉換成 byte 數(shù)字,而反序列化就是按照這種規(guī)則再去把字節(jié)流轉換成對應的類型數(shù)據(jù)。這些都是基于某種規(guī)則的基礎上,使用技術的手段去封裝的結果。
3. 通訊協(xié)議
3.1 協(xié)議架構
思路架構圖:
首先,我們先來了解協(xié)議在整個通訊當中的扮演的角色,如下圖所示:
如上圖所示,客戶端和服務端之間的通訊流程:
客戶端發(fā)送數(shù)據(jù)
- 客戶端先把一個對象序列化成字節(jié)流;
- 然后把字節(jié)流根據(jù)協(xié)議把字節(jié)流組裝好;
- 最后轉換成二進制傳輸?shù)骄W(wǎng)絡。
服務端接受數(shù)據(jù)
- 從網(wǎng)絡中讀取二進制數(shù)據(jù)到本地的緩沖區(qū);
- 根據(jù)協(xié)議的規(guī)則讀取指定數(shù)據(jù),并且識別是否是完整的數(shù)據(jù)包;
- 如果是完整的數(shù)據(jù)包,則轉換成實體對象。
由此可見,協(xié)議主要是管理字節(jié)流格式的一種規(guī)則,如果把協(xié)議環(huán)節(jié)去掉,那么服務端就無法知道字節(jié)流的結束位置。
3.2 協(xié)議設計
協(xié)議介紹:
- 協(xié)議標識符,以一個固定數(shù)作為標識符,占用 4 個字節(jié),主要目的是用來識別協(xié)議的開頭,只要是以該標識開頭的協(xié)議則進行處理,否則不處理。主要目的是提高處理性能問題,如果隨便一個請求都需要進行處理,但是最終處理起來發(fā)現(xiàn)協(xié)議格式不對,拋異常,肯定會影響系統(tǒng)性能;
- 數(shù)據(jù)長度,占用 4 個字節(jié),標識數(shù)據(jù)的真實長度,獲取到該值后,往后讀取指定長度的數(shù)據(jù)即可。主要目的是防止粘包和拆包安全性問題;
- 指令,協(xié)議是某個應用所有的業(yè)務公用的一種規(guī)則,那么應該如何區(qū)分是哪種業(yè)務呢?這里主要通過指令來進行區(qū)分;
- 數(shù)據(jù),這部分存儲的是真實的數(shù)據(jù)。
這算是比較簡單,并且常用的設計思路,主要和 Netty 內置的基于長度域拆包器類似,基本上都是有一個字段是用來存儲真實的數(shù)據(jù)長度,這樣才能準確的讀取數(shù)據(jù)的完整內容。當然,還可以在該設計基礎上加上更多的字段,比如:使用的序列號技術、協(xié)議版本號等等。
3.3 技術棧說明
相信到這里,大家對協(xié)議基本上有一個簡單的認識了,其實協(xié)議并不難,它只是一個約束而已,那么我們如何通過技術的實現(xiàn),讓協(xié)議生效呢?主要的核心思想如下:
- 序列化和發(fā)序列話技術,這個在 Netty 的編解碼的時候已經講過,序列化可以把對象轉化成字節(jié)流,反序列化可以把字節(jié)流轉換成對象;
- 字節(jié)容器(字節(jié)緩沖區(qū)),必須按照協(xié)議的字段順序往字節(jié)容器里面存放對應的字節(jié)內容,然后把整個容器寫到網(wǎng)絡當中。這樣數(shù)據(jù)才能按照順序進行傳輸,服務端才能按照順序進行數(shù)據(jù)的讀取和處理。
4. 小結
本節(jié)主要介紹協(xié)議的思想,它就是一種規(guī)則,客戶端和服務端必須需要遵守的規(guī)則,才能保證數(shù)據(jù)的安全性。其次,講解了協(xié)議在客戶端和服務端通訊當中所扮演的角色,如果沒有協(xié)議,那么服務端一直讀取字節(jié)流,根本無法知道數(shù)據(jù)的完整性。最后,大概介紹了協(xié)議設計的大概思想,主要核心字段有四個,分別是協(xié)議標識符、數(shù)據(jù)長度、指令、數(shù)據(jù),這四個字段是滿足協(xié)議的基本元素,可以根據(jù)實際業(yè)務再進行擴展字段。