【问题标题】:Azure Blob: "The condition specified using HTTP conditional header(s) is not met"Azure Blob:“不满足使用 HTTP 条件标头指定的条件”
【发布时间】:2011-07-02 22:04:22
【问题描述】:

我在运行我的应用程序时遇到了这个异常。它也发生在真正的 Azure blob 存储中。

我已经向 Fiddler 捕获了导致此问题的请求:

GET http://127.0.0.1:10000/devstoreaccount1/ebb413ed-fdb5-49f2-a5ac-74faa7e2d3bf/8844c3ec-9e4b-43ec-88b2-58eddf65fc0a/perro?timeout=90 HTTP/1.1
x-ms-version: 2009-09-19
User-Agent: WA-Storage/6.0.6002.18006
x-ms-range: bytes=0-524304
If-Match: 0x8CDA190BD304DD0
x-ms-date: Wed, 23 Feb 2011 16:49:18 GMT
Authorization: SharedKey devstoreaccount1:5j3IScY9UJLN3o1ICWKwVEazO4/IDJG796sdZKqHlR4=
Host: 127.0.0.1:10000

这是回应:

HTTP/1.1 412 The condition specified using HTTP conditional header(s) is not met.
Content-Length: 252
Content-Type: application/xml
Server: Windows-Azure-Blob/1.0 Microsoft-HTTPAPI/2.0
x-ms-request-id: fbff9d15-65c8-4f21-9088-c95e4496c62c
x-ms-version: 2009-09-19
Date: Wed, 23 Feb 2011 16:49:18 GMT

<?xml version="1.0" encoding="utf-8"?><Error><Code>ConditionNotMet</Code><Message>The condition specified using HTTP conditional header(s) is not met.
RequestId:fbff9d15-65c8-4f21-9088-c95e4496c62c
Time:2011-02-23T16:49:18.8790478Z</Message></Error>

当我使用从这一行检索到的 Stream 时会发生这种情况:

blob.OpenRead();

为什么 ETAG 在读操作中介意?我怎样才能避免这个问题?

每次我在 blob 存储上启动多个并行任务时都会发生这种情况。

如果我使用:

blob.OpenRead(new BlobRequestOptions() { AccessCondition = AccessCondition.IfMatch("*") });

我得到了这个没有内部异常的异常(在它有一个带有详细信息的 WebException 之前),或者是 Fiddler 中的一条失败行:

Microsoft.WindowsAzure.StorageClient.StorageClientException was unhandled
  Message=The conditionals specified for this operation did not match server.
  Source=mscorlib
  StackTrace:
    Server stack trace: 
       at Microsoft.WindowsAzure.StorageClient.Tasks.Task`1.get_Result()
       at Microsoft.WindowsAzure.StorageClient.Tasks.Task`1.ExecuteAndWait()
       at Microsoft.WindowsAzure.StorageClient.TaskImplHelper.ExecuteImpl[T](Func`2 impl)
       at Microsoft.WindowsAzure.StorageClient.BlobReadStream.Read(Byte[] buffer, Int32 offset, Int32 count)
       at System.IO.BinaryReader.ReadBytes(Int32 count)
       at System.Runtime.Serialization.Formatters.Binary.SerializationHeaderRecord.Read(__BinaryParser input)
       at System.Runtime.Serialization.Formatters.Binary.__BinaryParser.ReadSerializationHeaderRecord()
       at System.Runtime.Serialization.Formatters.Binary.__BinaryParser.Run()
       at System.Runtime.Serialization.Formatters.Binary.ObjectReader.Deserialize(HeaderHandler handler, __BinaryParser serParser, Boolean fCheck, Boolean isCrossAppDomain, IMethodCallMessage methodCallMessage)
       at System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Deserialize(Stream serializationStream, HeaderHandler handler, Boolean fCheck, Boolean isCrossAppDomain, IMethodCallMessage methodCallMessage)
       ...........

提前致谢。

【问题讨论】:

    标签: http azure blob azure-blob-storage azure-storage


    【解决方案1】:

    Buff...谜团解开了!

    好吧,当您执行CloudBlob.OpenRead() 时,客户端库正在执行两个操作:

    首先,获取blob块列表:

    GET /devstoreaccount1/etagtest/test2.txt?comp=blocklist&blocklisttype=Committed&timeout=90 HTTP/1.1
    x-ms-version: 2009-09-19
    User-Agent: WA-Storage/6.0.6002.18006
    x-ms-date: Wed, 23 Feb 2011 22:21:01 GMT
    Authorization: SharedKey devstoreaccount1:SPOBe/IUrZJvoPXnAdD/Twnppvu37+qrUbHnaBHJY24=
    Host: 127.0.0.1:10000
    
    HTTP/1.1 200 OK
    Transfer-Encoding: chunked
    Content-Type: application/xml
    Last-Modified: Wed, 23 Feb 2011 22:20:33 GMT
    ETag: 0x8CDA1BF0593B660
    Server: Windows-Azure-Blob/1.0 Microsoft-HTTPAPI/2.0
    x-ms-request-id: ecffddf2-137f-403c-9595-c8fc2847c9d0
    x-ms-version: 2009-09-19
    x-ms-blob-content-length: 4
    Date: Wed, 23 Feb 2011 22:21:02 GMT
    

    注意响应中的 ETag。

    其次,我猜是开始检索它,现在注意请求中的ETag:

    GET /devstoreaccount1/etagtest/test2.txt?timeout=90 HTTP/1.1
    x-ms-version: 2009-09-19
    User-Agent: WA-Storage/6.0.6002.18006
    x-ms-range: bytes=0-525311
    If-Match: 0x8CDA1BF0593B660
    x-ms-date: Wed, 23 Feb 2011 22:21:02 GMT
    Authorization: SharedKey devstoreaccount1:WXzXRv5e9+p0SzlHUAd7iv7jRHXvf+27t9tO4nrhY5Q=
    Host: 127.0.0.1:10000
    
    HTTP/1.1 206 Partial Content
    Content-Length: 4
    Content-Type: text/plain
    Content-Range: bytes 0-3/4
    Last-Modified: Wed, 23 Feb 2011 22:20:33 GMT
    ETag: 0x8CDA1BF0593B660
    Server: Windows-Azure-Blob/1.0 Microsoft-HTTPAPI/2.0
    x-ms-request-id: db1e221d-fc61-4837-a255-28b1547cb5d7
    x-ms-version: 2009-09-19
    x-ms-lease-status: unlocked
    x-ms-blob-type: BlockBlob
    Date: Wed, 23 Feb 2011 22:21:02 GMT
    

    如果另一个 WebRole 在调用之间的 blob 中做某事会发生什么? 是的比赛条件

    解决方案:使用CloudBlob.DownloadToStream(),该方法只发出一次调用:

    GET /devstoreaccount1/etagtestxx/test2.txt?timeout=90 HTTP/1.1
    x-ms-version: 2009-09-19
    User-Agent: WA-Storage/6.0.6002.18006
    x-ms-date: Wed, 23 Feb 2011 22:34:02 GMT
    Authorization: SharedKey devstoreaccount1:VjXIO2kbjCIP4UeiXPtxDxmFLeoYAKOqiRv4SV3bZno=
    Host: 127.0.0.1:10000
    
    HTTP/1.1 200 OK
    Content-Length: 4
    Content-Type: text/plain
    Last-Modified: Wed, 23 Feb 2011 22:33:47 GMT
    ETag: 0x8CDA1C0DEB562D0
    Server: Windows-Azure-Blob/1.0 Microsoft-HTTPAPI/2.0
    x-ms-request-id: 183a05bb-ea47-4811-8768-6a62195cdb64
    x-ms-version: 2009-09-19
    x-ms-lease-status: unlocked
    x-ms-blob-type: BlockBlob
    Date: Wed, 23 Feb 2011 22:34:02 GMT
    

    明天早上我会在工作中练习这个,看看会发生什么。

    【讨论】:

    • 您应该通知 MS,他们的服务器正在发送无效的 ETag,并且当客户端没有请求时,他们不应该返回部分响应 (206)。
    • 我把它放在 MSDN 论坛上,但没有人回答。
    【解决方案2】:

    你仍然可以使用 OpenRead,你需要像下面的代码一样传递 OperationContext 实例:

    // cloudBlob instance of CloudPageBlob
    
     OperationContext context = new OperationContext();
     context.SendingRequest += (sender, e) => { 
         e.Request.Headers["if-match"] = "*";
     };
    
     using (AutoResetEvent waitHandle = new AutoResetEvent(false))
     {
         cloudBlob.StreamMinimumReadSizeInBytes = 16385;
         var result = cloudBlob.BeginOpenRead(null, null, context,
             ar => waitHandle.Set(),
             null);
         waitHandle.WaitOne();
         using (Stream blobStream = vhd.EndOpenRead(result))
         {
             var k = blobStream.ReadByte();
         }
     }
    

    【讨论】:

      【解决方案3】:

      想到的一件事是 ETag 在

      If-Match: 0x8CDA190BD304DD0
      

      格式错误;有效的(强)etag 总是用双引号括起来。

      不知道这是否与您的问题有关。

      【讨论】:

      • 实际上,我在某处读到过,当 etag 的格式无效时,会返回 HTTP 412。我不知道 ETAG 是从哪里来的。
      • 我预计格式错误的 etag 会出现 400(错误请求),但我可以看到为什么服务器会返回 412(当它允许解析标头时)
      【解决方案4】:

      如果您不想使用 DownloadToStream 将 blob 数据存储在内存中,并且仍想使用 blob 读取,那么您可以在读取操作上添加访问条件,该条件与参考 blob 上可用的任何 Etag 匹配,如下所示

      var accessCondition = new AccessCondition();
      var blobRequestOptions = new BlobRequestOptions();
      var operationContext = new OperationContext();
      
      // Added match of any ETag access condition so that it will not cause any issue due to ongoing concurrent modification on the same blob
      operationContext.SendingRequest += (sender, e) =>
      {
          if (e.Request.Headers.Contains("if-match"))
          {
              e.Request.Headers.Remove("if-match");
          }
          e.Request.Headers.Add("if-match", "*");
      };
      
      var blobStream = await blobRef.OpenReadAsync(accessCondition, blobRequestOptions, operationContext);
      

      【讨论】:

        猜你喜欢
        • 2020-09-30
        • 2021-06-16
        • 2017-04-21
        • 2011-09-01
        • 2018-10-18
        • 2016-08-10
        • 1970-01-01
        • 2023-02-22
        • 1970-01-01
        相关资源
        最近更新 更多