Ale*_*lex 4 .net-core azure-blob-storage azure-storage-account
我正在尝试重现使用 AppendBlobs 时在生产服务器上看到的问题。
文档指出
追加 blob 中的每个块可以具有不同的大小,最大可达 4 MiB,并且追加 blob 最多可包含 50,000 个块。因此,附加 blob 的最大大小略大于 195 GiB(4 MiB X 50,000 块)。
这与我在生产应用程序中看到的情况相符,而且我确实看到了这些异常:
请求正文太大,超出了最大允许限制。
RequestId:3cb3ffd7-001e-0087-5789-ae3e0c000000
时间:2023-07-04T15:10:01.2687679Z
状态:413(请求正文太大,超出了最大允许限制。) ErrorCode:RequestBodyTooLarge
我遇到的问题是我无法在测试中重现此问题。
下面是一个最小的可重现示例,它本质上是通过将一堆 GUID 序列化为字符串来创建指定大小的内存流。
然后我用来AppendBlob附加斑点......
我可以看到memoryStream.Length确实大于4mb。
然而,令人费解的是,这确实有效。文件已正确上传到 Blob 存储,没有任何异常。
我已经找到了“修复”异常的方法(例如,对内存流进行分块),但我试图首先在测试中重现此问题,但我似乎无法在任何地方重现该错误。
有什么想法吗?
[Fact]
public async Task Can_append_blob_even_if_larger_than_4mb()
{
var containerClient = new BlobServiceClient(ConnectionString)
.GetBlobContainerClient("test-123");
await containerClient.CreateIfNotExistsAsync();
var outputFilename = $"Test-{DateTime.UtcNow.Ticks}.txt";
var appendBlobClient = containerClient.GetAppendBlobClient(outputFilename);
await appendBlobClient.CreateIfNotExistsAsync();
var json = JsonConvert
.SerializeObject(CreateList(6));
var memoryStream = new MemoryStream(Encoding.UTF8.GetBytes(json));
await appendBlobClient
.AppendBlockAsync(memoryStream);
}
private static List<object> CreateList(int sizeInMb)
{
const int mbInBytes = 1024 * 1024;
var maxSizeInBytes = sizeInMb * mbInBytes;
var totalSize = 0;
var list = new List<object>();
while (totalSize < maxSizeInBytes)
{
var obj = Guid.NewGuid();
var serializedObj = JsonConvert.SerializeObject(obj);
var objectSize = Encoding.UTF8.GetBytes(serializedObj).Length;
if (objectSize + totalSize > maxSizeInBytes)
{
break;
}
list.Add(obj);
totalSize += objectSize;
}
return list;
}
Run Code Online (Sandbox Code Playgroud)
看看源码int AppendBlobClient.AppendBlobMaxAppendBlockBytes
这是
public virtual int AppendBlobMaxAppendBlockBytes =>
ClientConfiguration.Version < BlobClientOptions.ServiceVersion.V2022_11_02
? Constants.Blob.Append.Pre_2022_11_02_MaxAppendBlockBytes
: Constants.Blob.Append.MaxAppendBlockBytes;
Run Code Online (Sandbox Code Playgroud)
这些常数是:
public const int Pre_2022_11_02_MaxAppendBlockBytes = 4 * Constants.MB; // 4MB
public const int MaxAppendBlockBytes = 100 * Constants.MB; // 100MB
Run Code Online (Sandbox Code Playgroud)
这个更大的尺寸尚未被记录。Azure.Storage.Blobs Version 12.17.0这是在2023-07-11 发布的包中定义的。
然而,在之前的包版本中,12.16.0我们看到了一些不同的东西:
public virtual int AppendBlobMaxAppendBlockBytes => Constants.Blob.Append.MaxAppendBlockBytes;
const int MaxAppendBlockBytes = 4 * Constants.MB; // 4MB
Run Code Online (Sandbox Code Playgroud)
假设:
测试代码和容器使用新的、更大的 100Mb 值。失败的代码使用较小的 4Mb 值。
看起来此检查是由Azure执行的,而不是由 Azure 客户端代码执行的,因此更新 Azure 客户端包本身并不能解决问题;事实上,如果它告诉您可以写入 100Mb,而您却不能,则情况可能会更糟,反之亦然。
这可以解释为什么最近创建的容器可以工作,而旧的容器却不能工作。Azure 中的此大小限制是容器还是帐户设置?可以在现有容器上进行非破坏性更改吗?不幸的是,这还没有记录。
您可以使用选项控制此设置,例如
var opts = new BlobClientOptions(BlobClientOptions.ServiceVersion.V2021_12_02);
var client = new AppendBlobClient(uri, creds, opts);
Run Code Online (Sandbox Code Playgroud)
但是,虽然这样设置int AppendBlobClient.AppendBlobMaxAppendBlockBytes,但它本身并不会导致“分块”,您仍然必须像这样附加最大大小的块。
文档仍然主要只谈论 4Mb,但请参阅“Azure 存储的版本控制”:
最大附加块内容长度已从 4 MiB 提高到 100 MiB。
| 归档时间: |
|
| 查看次数: |
217 次 |
| 最近记录: |