【问题标题】:Optimistic concurrency for Azure Storage blob always throws HTTP 412Azure 存储 blob 的乐观并发总是抛出 HTTP 412
【发布时间】:2018-10-02 16:17:07
【问题描述】:

为了实现 Azure 存储 blob 的乐观并发,我正在基于 blob 属性中的 ETag 值构造 If-Match AccessCondition

如果另一个进程更新了 blob,则 blob 服务应返回 HTTP 412(前提条件失败)状态消息。但是,该服务总是返回此 412 状态。

对于此示例,我使用存储资源管理器手动查找了 ETag 值。

重现问题的最小 sn-p 是:

var storage = CloudStorageAccount.Parse(connectionString);

var blobClient = storage.CreateCloudBlobClient();

var container = blobClient.GetContainerReference("foo");

var blob = container.GetBlockBlobReference("foo/1");

await blob.UploadTextAsync(
          "test", 
           Encoding.UTF8,
           AccessCondition.GenerateIfMatchCondition("\"0x1A52537587A1234\""),
           new BlobRequestOptions(),
           null);

【问题讨论】:

    标签: .net azure


    【解决方案1】:

    问题是我不小心用错了blobName

    var blob = container.GetBlockBlobReference("foo/1"); 
    

    应该是:

    var blob = container.GetBlockBlobReference("1");
    

    否则 ETag 检查将正确失败,因为没有名称为 foo/1 的 blob。

    【讨论】:

      【解决方案2】:

      当您上传具有特定 ETAG 值的 blob 时,它将首次工作。但是,当您第二次上传具有相同 ETAG 的 blob 时,它将引发 412 错误。因为一旦你操作了 blob,它的ETAG 就会更新。

      blob 和容器的乐观并发

      对此类对象执行更新的用户可以发送原始 ETag 以及条件标头,以确保仅在满足特定条件时才会发生更新 - 在这种情况下,条件是 @987654326 @header,要求Storage Service保证更新请求中指定的ETag的值与Storage Service中存储的值一致。

      // Retrieve Etag from the response of an earlier UploadText blob operation.
      string orignalETag = blockBlob.Properties.ETag;
      // This code simulates an update by a third party.
      string helloText = "Blob updated by a third party.";
      // No etag, provided so orignal blob is overwritten (thus generating a new etag)
      blockBlob.UploadText(helloText);
      Console.WriteLine("Blob updated. Updated ETag = {0}", blockBlob.Properties.ETag);
      // Now try to update the blob using the orignal ETag provided when the blob was created
      try
      {
           Console.WriteLine("Trying to update blob using orignal etag to generate if-match access condition");
           blockBlob.UploadText(helloText,accessCondition:
           AccessCondition.GenerateIfMatchCondition(orignalETag));
      }
      catch (StorageException ex)
      {
           if (ex.RequestInformation.HttpStatusCode == (int)HttpStatusCode.PreconditionFailed)
           {
                Console.WriteLine("Precondition failure as expected. Blob's orignal etag no longer matches");
           }
      }
      

      更多详情可以参考这个article

      【讨论】:

      • 感谢您的回答,但它没有回答我的问题。我将原始 ETag 与 If-Match 条件一起传递。但是即使博客没有被第三方更新,操作也会总是抛出412。
      • 这很奇怪。我用原始 ETAG 测试了你的代码,效果很好。
      猜你喜欢
      • 1970-01-01
      • 2022-01-15
      • 1970-01-01
      • 2010-12-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-05-04
      • 2012-03-02
      相关资源
      最近更新 更多