2

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

我有一个架构,其中服务器保持与客户端的终生持久连接(通过 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
{

}

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

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

4

1 回答 1

4

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

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

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

示例请求标头:

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

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

于 2012-06-18T13:03:56.810 回答