2011-02-23 9 views
7

Obtuve esta excepción cuando ejecuto mi aplicación. Ocurre también en el almacenamiento real de blobs de Azure.Azure Blob: "No se cumple la condición especificada mediante encabezado (s) condicional (es) HTTP"

he cogido con Fiddler la solicitud que crea este problema:

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 

Y esta es la respuesta:

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> 

Sucede cuando se utiliza la corriente recuperada de esta línea:

blob.OpenRead(); 

¿Por qué las mentes de ETAG en una operación de lectura? ¿Cómo puedo evitar este problema?

Ocurre cada vez que ejecuto varias tareas paralelas haciendo cosas en el almacenamiento de blob.

si uso:

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

tengo esta excepción, sin nadie interior (antes de que tuviera WebException con los detalles), o bien un fallo de línea en 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) 
     ........... 

Gracias de avanzar.

Respuesta

6

Bufff ... misterio resuelto!

Bueno, cuando se hace una CloudBlob.OpenRead(), la biblioteca cliente está haciendo dos operaciones:

primer lugar, obtener la lista de bloqueo burbuja:

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 

Atención a la ETag en la respuesta.

En segundo lugar, supongo que de inicio para recuperarlo, y ahora la atención a la ETag en la solicitud:

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 

Qué sucede si otro WebRole hacer algo en la burbuja entre la llamada? SÍ una condición de carrera.

Solución: Uso CloudBlob.DownloadToStream(), ese método sólo se emite una llamada:

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 

voy a poner esto en práctica mañana por la mañana en el trabajo y ver lo que sucede.

+0

Utilice CloudBlob.DownloadToStream hizo el truco :) – vtortola

+0

Debe notificar a MS que su servidor está enviando ETags no válidos, y que no deben devolver una respuesta parcial (206) cuando el cliente no lo solicitó. –

+0

Lo puse en los foros de MSDN, pero nadie responde. – vtortola

1

Una cosa que viene a la mente es que la ETag en

If-Match: 0x8CDA190BD304DD0 

es incorrecto; un etag válido (fuerte) siempre está entre comillas dobles.

No sé si esto tiene algo que ver con tu problema.

+0

En realidad, yo he leído en alguna parte que HTTP 412 se devuelve cuando el etag tiene un formato no válido. Lo que no sé es de dónde viene ese ETAG. – vtortola

+0

aquí: http://social.msdn.microsoft.com/Forums/en-US/windowsazuredata/thread/386afc5e-9bd3-490b-98d7-22fd03bda3a9/ – vtortola

+0

+1 Para la mención de cumplimiento de especificación. – Gumbo

1

Puede seguir utilizando OpenRead, lo necesario para pasar OperationContext ejemplo, como a continuación código:

// 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(); 
    } 
} 
Cuestiones relacionadas