DeflateStream and/or CryptoStream 在 TPL Dataflow TransformBlock 中的使用

Usage of DeflateStream and/or CryptoStream in TPL Dataflow TransformBlock

我正在使用 TPL 数据流块来实现基于数据包的网络协议。这个协议是固定的,我不能改变。大部分会有小包,但包很多。

我有一个连接到服务器并读取原始数据包的客户端组件。然后将这些原始数据包作为 MemoryStreams 发布到 BufferBlock,然后在 TransformBlock 中根据数据包解码为数据包结构 type/id.

为了发送数据包,这个过程与另一个数据流块链相反。据我所知,所有这些都运行良好。

问题是这些数据包可能会或可能不会被压缩,并且可能会或可能不会被加密,具体取决于服务器响应。我会用新的 TransformBlocks 解决这个问题(以解压缩为例):

static TransformBlock<Stream, Stream> CreateDecompressorBlock(ProtocolContext context)
{
    return new TransformBlock<Stream, Stream>(stream =>
    {
        if (!context.CompressionEnabled) return stream;
        return new DeflateStream(stream, CompressionMode.Decompress);
    }
}

但是在我看来这不是正确的方法。据我了解,DeflateStream(和 CryptoStream)在读取数据时对其进行解码。这意味着当我解码数据包内容时,数据被解码,而不是在 TransformBlock 本身内部,在那里只创建了包装器 Stream。这似乎会绕过数据流块的优势。

所以我想到了另一个解决方案,我没有返回 DeflateStream/CryptoStream,而是将其读入另一个 MemoryStream:

static TransformBlock<Stream, Stream> CreateDecompressorBlock(ProtocolContext context)
{
    return new TransformBlock<Stream, Stream>(stream =>
    {
        if (!context.CompressionEnabled) return stream;
        using (var deflate = new DeflateStream(stream, CompressionMode.Decompress))
        {
            var ms = new MemoryStream();
            deflate.CopyTo(ms);
            return ms;
        }
    }
}

现在看来这是在浪费内存。

所以我的问题是,仅包装流并让稍后解码数据包内容的 TransformBlock 完成工作是否足够,或者我应该使用更多内存然后可能有更好的分离和并行性? (虽然我不认为解码会是瓶颈,这将是网络)。

或者是否有一种模式可以与 TPL 数据流一起使用,从而更好地解决我的问题?

一如既往,这是一个权衡,只能由您做出决定。

我会选择最简单的解决方案,即连接两个块,并让写入块 "absorb" 增加压缩复杂性,因为 TDF 块可以在需要时增加它们的并行性。 但是,我只会在该块没有有限并行性(MaxDegreeOfParallelism)的情况下这样做。

如果有限制,那么我会按照你描述的那样处理压缩块中的实际压缩。这种行为可以在非常高的并行度下完成,而且这些内存缓冲区似乎并不是一个大问题。

如果是,您可以添加一个缓冲池,这样您的缓冲区计数将被限制为块的 MaxDegreeOfParallelism,并且您只需要在应用程序的生命周期内分配一次这些缓冲区。