AppendBlockAsync本地可传超4MB数据,Azure环境报错却无法复现?
关于Azure AppendBlob生产环境413异常无法在测试环境复现的问题
我在Azure App Service生产服务器使用AppendBlob时遇到问题,根据官方文档说明:
追加 blob 中的每个块可以是不同的大小,最大为 4 MiB,一个追加 blob 最多可包含 50,000 个块。因此追加 blob 的最大大小略超过 195 GiB(4 MiB × 50,000 个块)。
生产环境确实出现了对应异常:
The request body is too large and exceeds the maximum permissible limit.
RequestId:3cb3ffd7-001e-0087-5789-ae3e0c000000
Time:2023-07-04T15:10:01.2687679Z
Status: 413 (The request body is too large and exceeds the maximum permissible limit.)
ErrorCode: RequestBodyTooLarge
但我无法在测试环境复现该问题。我编写了最小复现示例,通过序列化大量GUID生成指定大小的内存流,调用AppendBlockAsync上传。可以看到memoryStream.Length确实超过4MB,但上传成功无异常。我已了解分块上传等解决方法,但希望先复现问题,却始终无法做到,请问这是什么原因?
[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; }
可能的原因分析
- 存储账户类型差异:Standard类型存储账户的AppendBlob单块上限为4MiB,而Premium类型存储账户的AppendBlob单块上限为100MiB。如果测试环境使用Premium存储、生产环境用Standard,就会出现测试能传大文件、生产报错的情况。
- SDK版本与自动分块逻辑:新版Azure.Storage.Blobs SDK会自动将超过单块上限的请求拆分为多个符合大小的块上传,而旧版SDK可能没有这个自动处理逻辑。若生产环境SDK版本低于测试环境,就会出现生产报错、测试成功的差异。
- 单位混淆:官方文档中的
4 MiB是二进制单位(410241024=4194304字节),日常说的4 MB是十进制单位(410001000=4000000字节)。如果测试代码生成的是略超过十进制4MB但未达到4MiB的内容,自然不会触发报错,但生产环境上传的内容确实超过了4MiB。 - 中间层请求限制:生产环境的Azure App Service可能配置了出站请求大小限制,或者存在代理/网关修改了请求体大小,导致实际到达存储服务的请求超出限制;而测试环境没有这类限制。
验证建议
- 对比生产与测试环境的存储账户类型,确认是否存在Standard/Premium的差异。
- 检查两边使用的Azure.Storage.Blobs SDK版本,将测试环境SDK降级到生产环境版本后重新测试。
- 精确计算测试代码生成的内存流大小,确认是否真的超过4MiB(4194304字节)。
- 尝试在测试环境中直接调用Append Blob的REST API(绕过SDK)上传超过4MiB的内容,看是否能触发413错误。
内容的提问来源于stack exchange,提问作者Alex
相关产品推荐
相关产品推荐

