這是接上一篇文章《RSF 分佈式服務框架設計》以後的續做,主要是 Hasor-RSF 協議層的設計。 sql
RSF 的協議層設計能夠很複雜也能夠很簡單。複雜是指這一層能夠嵌套多層協議棧,讓 RSF 的交互數據能夠跑在各類協議之上,例如:HTTP、RTMP、也能夠跑在相對底層的協議例如:TCP、UDP。 安全
RSF 在協議層的設計上須要保留可能未來嵌套其它協議的支持,但不要設計的過於複雜。所以 RSF 的協議層的實現應該被分爲兩層,以下:
服務器
位於底層的傳輸協議能夠是 TCP、UDP、RTMP、HTTP、等等各種聽過或者沒聽過的網絡協議。對於這些傳輸協議的要求只有一個 -- 那就是能夠傳輸 RSF 數據包。 網絡
在 RSF 初期徹底能夠忽略傳輸協議這一層的設計,只要將 RSF 數據包丟到網絡上而後遠程程序接收到便可。由於傳輸協議無外乎是至關於給 RSF 數據包套了一層馬甲,而這層馬甲在初期做用並不大,能夠隨着完善逐步豐富。 數據結構
接下來就是最關鍵的部分RSF 數據包的格式了,RSF 數據包的大致格式是「定長包頭 + 變長包體」這種形式。而且協議被設計成爲無狀態的。 併發
RSF數據交互形式: 框架
RSF交互協議採用(請求/響應)這種模式,客戶端發送某種類型的RSF數據包,服務器響應這種類型的請求。不須要握手協議。同時也是無狀態的。 分佈式
RSF數據包格式: spa
請求.net
* RSF 1.0 Request 協議 * --------------------------------------------------------bytes =13 * byte[1] version RSF版本(0xC1 or 0x81) * byte[8] requestID 請求ID * byte[1] keepData 保留區 * byte[3] contentLength 內容大小(max ~ 16MB) * --------------------------------------------------------bytes =10 * byte[2] servicesName-(attr-index) 遠程服務名 * byte[2] servicesGroup-(attr-index) 遠程服務分組 * byte[2] servicesVersion-(attr-index) 遠程服務版本 * byte[2] servicesMethod-(attr-index) 遠程服務方法名 * byte[2] serializeType-(attr-index) 序列化策略 * --------------------------------------------------------bytes =1 ~ 1021 * byte[1] paramCount 參數總數 * byte[4] ptype-0-(attr-index,attr-index) 參數類型1 * byte[4] ptype-1-(attr-index,attr-index) 參數類型2 * ... * --------------------------------------------------------bytes =1 ~ 1021 * byte[1] optionCount 選項參數總數 * byte[4] attr-0-(attr-index,attr-index) 選項參數1 * byte[4] attr-1-(attr-index,attr-index) 選項參數2 * ... * --------------------------------------------------------bytes =6 ~ 8192 * byte[2] attrPool-size (Max = 2047) 池大小 0x07FF * byte[4] att-length 屬性1大小 * byte[4] att-length 屬性2大小 * ... * --------------------------------------------------------bytes =n * dataBody 數據內容 * bytes[...]
響應
* RSF 1.0 Response 協議 * --------------------------------------------------------bytes =13 * byte[1] version RSF版本(0xC1 or 0x81) * byte[8] requestID 包含的請求ID * byte[1] keepData 保留區 * byte[3] contentLength 內容大小(max ~ 16MB) * --------------------------------------------------------bytes =8 * byte[2] status 響應狀態 * byte[2] serializeType-(attr-index) 序列化策略 * byte[2] returnType-(attr-index) 返回類型 * byte[2] returnData-(attr-index) 返回數據 * --------------------------------------------------------bytes =1 ~ 1021 * byte[1] optionCount 選項參數總數 * byte[4] attr-0-(attr-index,attr-index) 選項參數1 * byte[4] attr-1-(attr-index,attr-index) 選項參數2 * ... * --------------------------------------------------------bytes =6 ~ 8192 * byte[2] attrPool-size (Max = 2047) 池大小 * byte[4] att-length 屬性1大小 * byte[4] att-length 屬性2大小 * ... * --------------------------------------------------------bytes =n * dataBody 數據內容 * bytes[...]
上面列出了RSF在網絡通訊中所使用的數據包結構。
RSF數據包的主要結構是: 「Head + ContentLength + Content」,這種包結構能夠很方便的在底層網絡框架上予以解析並且簡單易懂。相比較淘寶 HSF2.0 的協議 RSF 的擴展性還算蠻強的。
Head 頭:
RSF 的協議頭採用 13 字節固定長度,其中包括了RSF在通訊上的 5 個基本數據(RSF協議標記、協議版本、包類型、請求ID,數據包長度)。
第一個字節中RSF目前規定只有:「0xC1」 和 「0x81」 兩個值。其中第1個二進制位用於表示RSF數據包,第2個二進制位用來表示請求或者響應,後面6個二進制位用來表示RSF協議版本。
因此有了:「0x80」能夠用來檢驗是否爲RSF數據包、「0xC0」用來表示RSF 請求數據包、「0x80」用來表示RSF響應數據包。因此依照這個規則「B2、F2、DA、FF」等值都是合法的,不過由於目前RSF協議版本只有1.0,因此只有 0xC1 和 0x81 是有效的。
接下來8個字節用來表示一個 long 值,這個值是請求ID。請求ID的做用是區分同一客戶端在併發調用的狀況下區分不一樣調用而設計的。
在接下來的 1 個字節爲保留位。隨後的 3 個字節表示一個 int 類型,這個值表示的是 RSF 頭以後的 RSF 數據包總長度。這樣就限制了RSF數據包大小最約 16MB。
Content 結構:
RSF 的包體中協議格式和傳輸的數據是分離設計的,這種設計會讓協議自己的結構顯得很是清晰。全部的屬性值都會保存在屬性池中,而且以其在屬性池中位值加以替代。例如:
服務名爲:「org.example.hello.MyService」的信息轉換爲二進制以後,將其放入屬性池,而後用其在屬性池中的位置加以表示(2字節 short 類型)。
此外對於鍵值這種結構的數據將會採用(4字節來表示),其中 key 由前兩個字節表示,value用後兩位字節表示。而這 4個字節剛好可使用 int 類型來表示。
依照上面兩個規則就造成了 RSF 請求響應的數據結構。
最後是屬性池的設計,屬性池的最大容量是 65535 條。依照現有的RSF協議規定根本沒法達到這個量級,因此是十分安全的。
屬性池中的數據都是 4 字節,用來表述內容大小。例如上面那個服務名其在屬性池中的值是 27。
最後 dataBody 部分將會按照屬性池中的順序一次將屬性內容排列下去。
假設提取位於屬性池 3 號位置的屬性屬性值是 23,其前面兩個屬性大小均爲 10 字節,那麼 3號屬性的實際位置就是 dataBody區域的 20~43 位置的數據。
屬性池的 0 號屬性:
屬性池中 0 號屬性是 RSF 協議中規定的固定屬性,其屬性值爲 0。做爲 0 長度的屬性在 dataBody 區域是不會產生任何數據輸出。