使用 protobuf 进行部分反序列化

Har*_*can 2 architecture serialization design-patterns protobuf-net

致 marc 或任何有 protobuf-net 经验的人:

我有一个架构,其中服务器与客户端保持终身持久连接(通过 TCP)。由于连接层/服务器应该具有较高的正常运行时间,因此它仅对消息进行反序列化并将其传递到应用程序服务器/层。它本身不包含商业逻辑。

 clients -> connection layer (deserialization) -> app layer (business logic)
Run Code Online (Sandbox Code Playgroud)

问题是,虽然我现在可以更改业务逻辑,但我无法更改应用程序层和客户端共享的模型,因为连接层依赖于反序列化的模型。

有没有办法让连接层仅将消息部分反序列化到基类,以用于转发/路由目的?

否则,我想我必须在基类中创建一个二进制字段,该字段按原样传递并由应用程序层反序列化。一级序列化,二级反序列化。

编辑:充实

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
{

}
Run Code Online (Sandbox Code Playgroud)

连接层不应该关心特定请求类型的结构。这样我就可以随意更改它们,只要客​​户端和应用程序层都同意。但目前连接层进行反序列化,因此它确实需要知道模型,任何更改都会迫使我重新启动连接服务器。

我只需要它进行足够的反序列化以进行路由,这意味着“用户信息”+“子类型名称/编号”。

jga*_*fin 5

首先:您不应该直接通过网络发送 protobuf 序列化消息,因为 TCP 是基于流的。您永远无法知道何时收到完整的消息。

正是WithLengthPrefix用于此目的。为所有消息添加二进制长度前缀,以便您可以知道完整消息何时到达。

如果我是你,我会创建一个包含足够路由信息的标头。长度是强制性的,但您也可以包含传输的消息的类型等。这意味着您只需检查每条消息的标头,而不必调用昂贵的反序列化。

请求标头示例:

  • 标头版本 ( byte)
  • 内容类型 ( byte) (您需要在某处创建映射)
  • 内容长度 ( int)

我目前正在为我的 Griffin.Networking ( http://github.com/jgauffin/griffin.networking ) 编写一个小插件,它将有一个小标头并使用 protobuf 来发送消息。关注项目以在提交时获取更新。