Azure Blob:“未满足使用 HTTP 条件标头指定的条件”
当我运行我的应用程序时,我遇到了这个异常。它也发生在真正的 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>
当我使用从这一行检索的流时会发生这种情况:
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)
...........
提前致谢。
I got this exception when I run my application. It happens also in the real Azure blob storage.
I've caught with Fiddler the request that creates this problem:
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
And this is the response:
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>
It happens when I use the Stream retrieved from this line:
blob.OpenRead();
Why the ETAG minds in a read operation? How may I avoid this problem?
It happens every time I launch several parallel tasks doing things on the blob storage.
If i use:
blob.OpenRead(new BlobRequestOptions() { AccessCondition = AccessCondition.IfMatch("*") });
I got this exception with no inner one (before it had a WebException with the details), either a fail line in 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)
...........
Thanks in advance.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
巴夫……谜团解开了!
好吧,当您执行 CloudBlob.OpenRead() 时,客户端库会执行两个操作:
首先,获取 blob 块列表:
注意响应中的 ETag。
其次,我想开始检索它,现在注意请求中的 ETag:
如果另一个 WebRole 在调用之间的 blob 中执行某些操作,会发生什么情况? 是的,竞争条件。
解决方案:使用 CloudBlob.DownloadToStream(),该方法仅发出一次调用:
我将在明天早上的工作中实践这一点,看看会发生什么。
Bufff... mistery solved!
Well, when you do a
CloudBlob.OpenRead()
, the client library is doing two operations:First, get the blob block list:
Attention to the ETag in the response.
Second, I guess that start to retrieve it, and now attention to the ETag in the request:
What happen if another WebRole do something in the blob between call? YES a race condition.
Solution: Use
CloudBlob.DownloadToStream()
, that method only issues one call:I will put this on practice tomorrow morning at work and see what happen.
您仍然可以使用 OpenRead,您需要传递 OperationContext 实例,如下代码所示:
You can still use OpenRead, you need to pass OperationContext instance like below code:
我想到的一件事是 ETag 格式
错误;有效(强)的 etag 始终用双引号引起来。
不过,不知道这是否与您的问题有关。
One thing that comes to mind is that the ETag in
is malformed; a valid (strong) etag is always in double quotes.
Dunno whether this has something to do with your problem, though.
如果您不想使用 DownloadToStream 将 blob 数据存储在内存中,但仍想使用 blob 读取,那么您可以在读取操作上添加访问条件,该条件与引用 blob 上可用的任何 Etag 相匹配,如下所示
If you don't want to store blob data in your memory with DownloadToStream and still want to use blob read then you can add access condition on a read operation which matches any Etag available on the reference blob Like below