最近這一個月都在反覆實作與檢示 Client Server 之間的資料交換架構. 一般最直觀的資料交換, 就是任何一方發送資料時先經過制式的序列化 (serialization, 或稱 deflating, marshalling) 程序, 把運行時結構化的數據資料成員重新排列成平面且緊密的純二進位資料流 (binary data stream), 然後將資料流送出, 接收方再透過相對應的反序列化程序 (deserialization, 或稱 inflating, unmarshalling) 把收到的資料流重組回結構化的數據.
這樣直觀的流程套用在開發專案時會遇到一個問題: 每種需要進行資料交換的結構化數據類型都必需要撰寫其專有的序列化/反序列化程序. 這樣的需求在結構化數據類型會隨專案開發的進度而大量增加時就會變得很繁瑣. 為了解決這種窘境, 我們會希望在序列化時盡量讓輸出的資料流保有某種程度上的自述性. 也就是說不管面對何種類型的數據類型, 序列化/反序列化的做法都要能是同一套, 序列化時除了資料本身之外, 還夾帶了這些資料的型態, 彼此的結構關系這類資訊, 提供反序列化程序檢示, 賴以重組回結構化的數據. 舉一個極端的例子: 進行序列化時, 將結構數據輸出為用 JSON 或 YAML 這類資料描述語言的描述語句, 反序列化時解析這些語句重組回結構化數據. 通常這些描述語言都已有很好的各類程序語言函式庫, 可提供現成的輸出描述語句和解析語句的功能.
輸出具有自述性的資料流會有個不良影響是會導致資料流的膨脹. 原本只要夾帶資料本身, 現在要多附加資料型態和結構關係, 所以因資料膨脹導致交換效能降低是必然的結果. 那麼在效能跟繁瑣之間有沒有妥協方案呢? Google 提倡的 protobuf 就是一例. 它的運作原理是, 把資料型態和結構化關係這類額外的資訊另外寫成 .proto 的文件 (protobuf 本身的資料描述語法), 透過 protobuf 提供的編譯功能編譯這些 .proto 文件產生專有的序列化/反序列化模組, 程式運行時再透過這些模組對於該資料類型進行序列化工作. 輸出的二進位資料流的緊密度和效能就由 protobuf 來背書, 理論上會比自述性資料流來得好, 因為要傳輸的資料較密(量較少)且序列化過程中做的事較少.
目前已實現基於 JSON 自述的序列化程序, 正朝 protobuf 前進. 由於需要交換的結構化數據都是用 XML Schema 定義, 所以要做 protobuf 的實現必需先克服由 XML Schema 自動生成 .proto 文件的這一步.
沒有留言:
張貼留言