【发布时间】:2012-09-19 06:28:28
【问题描述】:
我们正在开发用于流式传输大量数据的 WCF 服务,因此我们选择使用 WCF Streaming 功能和 protobuf-net 序列化。
上下文:
一般一个想法是序列化服务中的对象,将它们写入流并发送。 在另一端,调用者将收到一个 Stream 对象,它可以读取所有数据。
所以目前服务方法代码看起来有点像这样:
public Result TestMethod(Parameter parameter)
{
// Create response
var responseObject = new BusinessResponse { Value = "some very large data"};
// The resposne have to be serialized in advance to intermediate MemoryStream
var stream = new MemoryStream();
serializer.Serialize(stream, responseObject);
stream.Position = 0;
// ResultBody is a stream, Result is a MessageContract
return new Result {ResultBody = stream};
}
BusinessResponse 对象被序列化为 MemoryStream 并从方法返回。 在客户端,调用代码如下所示:
var parameter = new Parameter();
// Call the service method
var methodResult = channel.TestMethod(parameter);
// protobuf-net deserializer reads from a stream received from a service.
// while reading is performed by protobuf-net,
// on the service side WCF is actually reading from a
// memory stream where serialized message is stored
var result = serializer.Deserialize<BusinessResponse>(methodResult.ResultBody);
return result;
因此,当调用 serializer.Deserialize() 时,它从流 methodResult.ResultBody 中读取,同时在服务端 WCF 正在读取从 TestMethod 返回的 MemoryStream。
问题:
我们想要实现的是在服务端立即摆脱MemoryStream 和整个对象的初始序列化。
由于我们使用流式传输,我们希望避免在发送之前将序列化对象保留在内存中。
想法:
完美的解决方案是返回一个空的、定制的 Stream 对象(来自TestMethod()),并引用一个要序列化的对象(在我的示例中为“BusinessResponse”对象)。
因此,当 WCF 调用我的流的 Read() 方法时,我会在内部使用 protobuf-net 序列化一个对象,并将其返回给调用者,而不会将其存储在内存中。
现在有一个问题,因为我们真正需要的是在读取流的那一刻,可以逐个序列化一个对象。 我知道这是完全不同的序列化方式 - 我不想将对象推送到序列化程序,而是逐个请求序列化内容。
这种序列化是否可以使用 protobuf-net 以某种方式实现?
【问题讨论】:
-
这是一个对象吗?还是一系列对象(一个集合)?是否值得看这么多实际上取决于您的 WCF 配置 - 在大多数配置中,它总是将整个消息缓冲在内存中无论如何 - 所以不更改任何内容可能很容易。
-
嗨,Marc,WCF 配置为根本不使用缓冲——这就是流式传输的重点——我想减少服务器端的内存占用。此外,如果我想序列化对象集合,我会在每次客户端调用
Read()时使用SerializeWithLengthPrefix(),并且我的底层缓冲区小于请求的数据量。这里的问题是我希望能够拆分单个对象序列化。 -
有趣的问题。我认为这可以概括,本质上是一个欺骗流,它使读取和写入作为协同例程工作。如果你不介意有一个额外的线程,可以用一个简单的门来完成,但是 iirc Jon 有一些有趣的想法。我得看看然后再给你答复。但是,我可以毫无疑问地说,我不打算为此目的破解 protobuf-net 的核心 :)
-
有趣的问题。顺便说一句,考虑到 WCF 的复杂性和 protobuf 的使用,这个服务不会被一个不完全为这个服务编写的客户端互操作。在这种情况下,WCF 不是不必要的抽象层吗?我只是问,因为我现在还没有看到所有的好处。也许是请求部分的 WS-*?
-
@jhexp 你说的很对,protobuf 使服务的互操作性降低。但是这是内部使用的服务,可以根据客户的喜好选择或不选择 protobuf 序列化。
标签: c# wcf serialization streaming protobuf-net