16

アプリケーションを実行すると、この例外が発生しました。これは、実際のAzureBLOBストレージでも発生します。

この問題を引き起こすリクエストを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)
       ...........

前もって感謝します。

4

4 に答える 4

14

バフ...ミステリーが解決しました!

を実行するCloudBlob.OpenRead()と、クライアントライブラリは2つの操作を実行します。

まず、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が呼び出しの間にブロブで何かをした場合はどうなりますか?はい、競合状態です。

解決策:を使用するCloudBlob.DownloadToStream()と、そのメソッドは1回の呼び出しのみを発行します。

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

明日の朝、職場でこれを練習して、どうなるか見ていきます。

于 2011-02-23T22:36:30.750 に答える
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();
     }
 }
于 2013-10-09T17:07:28.460 に答える
1

頭に浮かぶことの1つは、ETagが

If-Match: 0x8CDA190BD304DD0

奇形です。有効な(強力な)etagは常に二重引用符で囲みます。

しかし、これがあなたの問題と関係があるかどうかはわかりません。

于 2011-02-23T18:47:57.937 に答える
0

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);
于 2021-02-02T05:45:37.507 に答える