c# - 使用 C# 将非常大的项目列表序列化到 Azure blob 存储中

标签 c# azure serialization protocol-buffers capnproto

我有一个很大的对象列表,需要稍后存储和检索。该列表将始终作为一个单元使用,并且不会单独检索列表项。该列表包含约 7000 个项目,总大小约为 1GB,但很容易升级到十倍或更多。

我们一直在使用BinaryFormatter.Serialize()进行序列化( System.Runtime.Serialization.Formatters.Binary.BinaryFormatter )。然后,该字符串作为 blob 上传到 Azure blob 存储。我们发现它通常快速且高效,但当我们使用更大的文件大小对其进行测试时,它变得不够充分,抛出 OutOfMemoryException 。据我了解,虽然我使用的是流,但我的问题是 BinaryFormatter.Serialize()方法必须首先将所有内容序列化到内存,然后才能上传 blob,从而导致出现异常。

二进制序列化器如下所示:

public void Upload(object value, string blobName, bool replaceExisting)
{
    CloudBlockBlob blockBlob = BlobContainer.GetBlockBlobReference(blobName);
    var formatter = new BinaryFormatter()
    {
        AssemblyFormat = FormatterAssemblyStyle.Simple,
        FilterLevel = TypeFilterLevel.Low,
        TypeFormat = FormatterTypeStyle.TypesAlways
    };

    using (var stream = blockBlob.OpenWrite())
    {
        formatter.Serialize(stream, value);
    }
}

formatter.Serialize(stream, value) 上发生 OutOfMemoryException线。

因此,我尝试使用不同的协议(protocol),Protocol Buffers。我尝试使用 Nuget 包 protobuf-net 和 Google.Protobuf 中的实现,但序列化速度非常慢(大约 30 分钟),而且据我所知,Protobuf 并未针对序列化大于 1MB 的数据进行优化。因此,我回到绘图板,发现了 Cap'n Proto,它 promise 通过使用内存映射来解决我的速度问题。我正在尝试使用 @marc-gravell 的 C# 绑定(bind),但在实现序列化器时遇到一些困难,因为该项目还没有完整的文档。此外,我不能 100% 确定 Cap'n Proto 是正确的协议(protocol)选择 - 但我正在努力在网上寻找任何替代建议。

如何以相当快的方式将非常大的项目集合序列化到 blob 存储,而不会遇到内存问题?

最佳答案

也许您应该切换到 JSON?

使用 JSON 序列化器,您可以在文件之间进行流式传输,并逐段序列化/反序列化(在读取文件时)。

您的对象能够很好地映射到 JSON 吗?

这是我用来获取 NetworkStream 并将其放入 Json 对象的方法。

    private static async Task<JObject> ProcessJsonResponse(HttpResponseMessage response)
    {
        // Open the stream the stream from the network
        using (var s = await ProcessResponseStream(response).ConfigureAwait(false))
        {
            using (var sr = new StreamReader(s))
            {
                using (var reader = new JsonTextReader(sr))
                {
                    var serializer = new JsonSerializer {DateParseHandling = DateParseHandling.None};

                    return serializer.Deserialize<JObject>(reader);
                }
            }
        }
    }

此外,您可以对流进行 GZip 压缩以减少文件传输时间。我们直接流式传输到 GZipped JSON,然后再返回。

编辑,虽然这是反序列化,但相同的方法应该适用于序列化

关于c# - 使用 C# 将非常大的项目列表序列化到 Azure blob 存储中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36477423/

相关文章:

c# - 配置 MassTransit 以反序列化多态属性

c# - 如何在wcf中序列化 protected 属性

c# - 创建多个具有相同签名的 Web Api

c# - asp.net:将多个 div 添加到同一页面

azure - DocumentDb 更改 Feed 事件类型?

azure - 在一个查询中查找匹配 PartitionKey 列表的实体,而无需执行 foreach

c# - 如何找出 map 上绘制的形状内的坐标?

c# - 检查计算机是否通过 Wake On Lan 激活

c# - Azure 在 blob 中搜索元数据

Javascript JSON 日期反序列化