Azure blob的阻止列表为空,但blob不为空!怎么会这样?

Mår*_*röm 6 azure azure-storage azure-storage-blobs

这个问题简而言之:

可以使用单个PUT请求创建块blob.这将创建一个带有已提交内容的blob,但blob 将没有任何已提交的块!

这意味着您不能假定已提交块的串联与已提交内容相同.

使用块blob时,你必须特别注意带有空块列表的blob,因为这样的blob 可能是也可能不是空的!


原来的问题:

Azure帐户中的一个存储blob具有空阻止列表,尽管它是非空的.

我正在检索这样的阻止列表(C#):

foreach (var block in _cloudBlob.DownloadBlockList(
    BlockListingFilter.Committed, 
    AccessCondition.GenerateLeaseCondition(_leaseId)))
{
    // ...
}
Run Code Online (Sandbox Code Playgroud)

foreach块中的代码未执行.返回的列表为空.

但是,当我检查时,blob报告它具有非零长度: _cloudBlob.Properties.Length

我也可以下载blob,看看它不是空的.

我错过了什么吗?当blob不是时,阻止列表如何为空?!

无论我是否使用BlockListingFilter.Committed,BlockListingFilter.Uncommitted或者BlockListingFilter.All; 清单仍然是空的!

UPDATE

我已将此blob复制到公共容器中,以便任何人都可以复制此问题.

以下是如何重现我无法理解的内容:

首先使用REST API从Azure获取blob属性:

HEAD http://dfdev.blob.core.windows.net/pub/test HTTP/1.1
Host: dfdev.blob.core.windows.net
Run Code Online (Sandbox Code Playgroud)

响应:

HTTP/1.1 200 OK
Content-Length: 66
Content-Type: application/octet-stream
Last-Modified: Sat, 02 Feb 2013 09:37:19 GMT
ETag: 0x8CFCF40075A5F31
Server: Windows-Azure-Blob/1.0 Microsoft-HTTPAPI/2.0
x-ms-request-id: 4b149a7e-2fcd-4ab4-8d53-12ef047cbfa1
x-ms-version: 2009-09-19
x-ms-lease-status: unlocked
x-ms-blob-type: BlockBlob
Date: Sat, 02 Feb 2013 09:40:54 GMT
Run Code Online (Sandbox Code Playgroud)

响应头告诉我们这是一个块blob,它的长度为66个字节.

现在从以下位置检索阻止列表:

http://dfdev.blob.core.windows.net/pub/test?comp=blocklist

回应机构:

<?xml version="1.0" encoding="utf-8"?><BlockList><CommittedBlocks /></BlockList>
Run Code Online (Sandbox Code Playgroud)

因此,blob没有任何已提交的块,仍然有66个字节的长度!

这是一个错误还是我误解了什么?

请帮帮我!

更新2

我发现如果我像这样上传blob:

container.GetBlockBlobReference("put-only")
    .UploadFromStream(File.OpenRead("test-blob"));
Run Code Online (Sandbox Code Playgroud)

...然后将一个PUT请求发送到Azure,并且blob获取一个空的阻止列表(就像上面一样).

但是,如果我像这样上传blob:

var blob = container.GetBlockBlobReference("put-block");
string blockId = Convert.ToBase64String(Guid.NewGuid().ToByteArray());
blob.PutBlock(blockId, File.OpenRead("test-blob"), null);
blob.PutBlockList(new string[] { blockId });
Run Code Online (Sandbox Code Playgroud)

...然后向Azure发送两个请求(一个用于放置块,另一个用于放置块列表).

第二个blob获得一个非空的阻止列表.

为什么单个PUT不会产生阻止列表?

我们难道不能依赖blob的已提交块的串联等于blob的实际内容吗?!

如果没有,我们如何确定阻止列表何时正常以及何时不是?

更新3

我已经为此实现了一个解决方法,我认为在我们遇到此问题的情况下就足够了.如果我们发现一个空的块列表和一个大于零的blob长度,那么我们将假设一切正常(虽然它确实不是)并继续使用Put Block和Put Block List重写该数据.下一个机会.

然而,尽管在我们的例子中这将起到作用,但是非空块blob可以具有已提交块的空列表仍然非常令人困惑!

这是Azure中的副设计吗?谁能解释一下发生了什么?

更新4

Microsoft 也在MSDN论坛上确认了此问题.陈艾伦引用:

我已经与产品团队确认过了.这是正常行为.x-ms-blob-content-length头是提交的blob的大小.在您的情况下,您使用Put Blob API,因此所有内容都上传到单个API中,并在同一请求中提交.因此,在Get Block List API的响应中,您会看到x-ms-blob-content-length标头的值为66,这意味着已提交的blob大小.

我们已经意识到Get Block List API的MSDN文档在此问题上并不十分明确,并且会对其进行处理.

Ser*_*ler 7

正如您在测试中发现的那样,查询使用Put Blob上传的块blob的块列表将返回一个空列表.这是设计的.

Storage Client库中的UploadFromStream API在决定是使用单个Put Blob操作还是一系列Put Block操作后跟Put块列表来上传blob之前进行一些检查.一个更改此行为的属性是SingleBlobUploadThresholdInBytes.

  • 好的。嗯,这很清楚。然而,这是否意味着我们实际上拥有三种斑点:页面斑点;块 blob 带块;和块 blob 没有块!?例如,如果我们想要将数据附加到块 blob,那么我们需要以完全不同的方式处理两种“类型”的块 blob。这对我来说确实感觉是一个糟糕的设计,但也许我错过了一些东西?不管怎样,你已经回答了我的问题——这是设计使然。谢谢你! (3认同)
  • 通过上传整个新 blob 来附加数据并不是一个好的解决方案。考虑一下当我们只想将几百个字节附加到一个大的现有 blob 时的情况。必须上传此更改的所有内容将是糟糕的设计。当仅通过附加创建 blob 时,就没有问题。但是,我们需要支持由单独的工具创建 blob 的情况。这些工具很可能使用单个 PUT 操作上传 blob,从而创建**没有**块的块 blob。 (2认同)