2012-06-15 30 views
1

馬克或任何人誰​​是在protobuf網經歷了部分反序列化:與protobuf的

我在服務器端對客戶終身持久連接(通過TCP)的架構。由於連接層/服務器應具有較高的正常運行時間,因此它僅對消息進行反序列化並將消息傳遞給應用服務器/層。它本身不包含商業邏輯。

clients -> connection layer (deserialization) -> app layer (business logic) 

問題是,雖然我現在可以進行更改BIZ邏輯,我不能改變由應用層和客戶機共享的模型,因爲在連接層依賴於模型進行解串行化。

是否有任何方法只有連接層爲了轉發/路由的目的,部分反序列化消息到基類?

否則,我想我將不得不在基類中創建一個二進制字段,該字段按原樣傳遞,並由應用層反序列化。一個階段的序列化,兩個階段的反序列化。

編輯:充實

class Message 
{ 
    User user; 
    // not much else in here, potentially routing information 
} 

class RequestType1: Message 
{ 
// lots of fields 
// which are specific to this type of request/reply 
} 

class RequestType2: Message 
{ 

} 

連接層不應該關心特定的請求類型的結構。這樣,只要客戶端和應用層都同意,我可以隨意更改它們。但是目前連接層執行反序列化,所以它需要知道模型,並且任何更改都迫使我重新啓動連接服務器。

我只是需要它反序列化足夠的路由,這意味着'用戶信息'+'子類型名稱/編號'。

+0

我想另一個選擇是在連接層和應用層之間創建一個反序列化/路由層。這部分是一個設計問題,而不僅僅是一個原始問題。 –

+1

你可以補充一點,I.e.一個完整的消息的例子(最好是一個小的消息),以及關於你想要的部分反序列化的字段等信息?另外,如果你*部分反序列化,你會通過下游 - 原始的完整信息?等高興地幫助,但需要更多的上下文。 –

+0

現在看看,也許它更有意義。 –

回答

2

首先:您不應該直接通過線路發送protobuf序列化消息,因爲TCP是基於流的。你永遠不知道你什麼時候收到完整的信息。

WithLengthPrefix僅用於此目的。用二進制長度前綴所有消息,以便您可以知道完整消息何時到達。

如果我是你,我會創建一個包含足夠的路由信息​​的頭。這個長度是強制性的,但你也可以包括傳輸消息的類型等。這意味着你只需要檢查每個消息的頭部,而不是調用昂貴的反序列化。

實施例請求頭:

  • 頭版本(byte
  • 內容類型(byte)(需要某處創建映射)
  • 內容長度(int

我目前正在爲我的Griffin.Networking(http://github.com/jgauffin/griffin.networking)寫一個小插件,它會有一個小標題並使用protobuf的消息。觀察項目以在提交時獲取更新。

+0

是的,我已經有一個大小前綴,現在添加了路由頭。將接受你的答案,因爲marc沒有發佈一個,你花了一些時間寫它。乾杯。 –

+0

如果這仍然是最新的,那真是太遺憾了。使用強烈定義的數據合約,可以實現流式序列化和未預知的消息長度。我已經使用JSON實現了這一點,並且目前正在使用該功能切換到BinaryWriter。好處是顯着降低峯值內存使用量,並縮短與等待消息建立相關的交貨時間。儘管如此,接口面臨的挑戰是確保反序列化的流按照正確的順序被消耗,如果有多個可枚舉的段。 (用IEnumerable <>和yield在C#中實現) – Todd