2015-09-11 7 views
6

Ich wusste, dass der Azure CloudAppendBlob vor Nebenläufigkeitsproblemen sicher war, da Sie nur an diesen Blobspeicher anhängen können und E-Tags nicht vergleichen müssen. Wie von diesem Beitrag erwähnt:Azure CloudAppendBlob-Fehler bei gleichzeitigem Zugriff

http://blogs.msdn.com/b/windowsazurestorage/archive/2015/04/13/introducing-azure-storage-append-blob.aspx

speziell:

Darüber hinaus unterstützt Anhängungs auf den gleichen Blobs mehrere Clients mit, ohne dass für die Synchronisation (im Gegensatz zu Block und Seiten-Blob) Schreiben

jedoch die folgende Einheit Test aufwirft:

412 Die angegebene Bedingung für die Append-Position wurde nicht erfüllt.

Stack-Trace

Microsoft.WindowsAzure.Storage.Blob.BlobWriteStream.Flush() 
Microsoft.WindowsAzure.Storage.Blob.BlobWriteStream.Commit() 
Microsoft.WindowsAzure.Storage.Blob.CloudAppendBlob.UploadFromStreamHelper 
Microsoft.WindowsAzure.Storage.Blob.CloudAppendBlob.AppendFromStream 
Microsoft.WindowsAzure.Storage.Blob.CloudAppendBlob.AppendFromByteArray 
Microsoft.WindowsAzure.Storage.Blob.CloudAppendBlob.AppendText 

Hier ist das Gerät zu testen. Vielleicht wird der Dienst Anfragen aus verschiedenen Kontexten behandeln, aber nicht so wie eine Parallele?

[TestMethod] 
    public void test_append_text_concurrency() 
    { 
     AppendBlobStorage abs = new AppendBlobStorage(new TestConnectConfig(), "testappendblob"); 

     string filename = "test-concurrent-blob"; 

     abs.Delete(filename);      

     Parallel.Invoke(
      () => { abs.AppendText(filename, "message1\r\n"); }, 
      () => { abs.AppendText(filename, "message2\r\n"); } 
     ); 

     string text = abs.ReadText(filename); 

     Assert.IsTrue(text.Contains("message1")); 
     Assert.IsTrue(text.Contains("message2")); 
    } 

Methode in AppendBlobStorage

public void AppendText(string filename, string text) 
    { 
     CloudAppendBlob cab = m_BlobStorage.BlobContainer.GetAppendBlobReference(filename); 

     // Create if it doesn't exist 
     if (!cab.Exists()) 
     { 
      try 
      { 
       cab.CreateOrReplace(AccessCondition.GenerateIfNotExistsCondition(), null, null); 
      } 
      catch { } 
     } 

     // Append the text 
     cab.AppendText(text);  
    } 

Vielleicht bin ich etwas fehlt. Der Grund, warum ich versuche, dies zu tun, da ich mehrere Web-Jobs habe, die alle in diesen Append-Blob schreiben können, und ich dachte, das war, wofür er entwickelt wurde?

+0

Ich habe auch gerade dies von mehreren Webjobs spinnen und etwas Text in den gleichen appendblob schreiben. Ich bekomme den gleichen Fehler. – James

+0

Beachten Sie, dass ich Version 5.0.2.0 von Microsoft.WindowsAzure.Storage (Ich habe auch versucht, gegen 5.0.3.0 Vorschau) – James

Antwort

5

Nach ein bisschen mehr Suche sieht es aus wie dies ein echtes Problem ist.

Ich denke AppendBlobStorage ist ziemlich neu. (Es gibt auch andere Probleme im Moment mit AppendBlobStorage

http://blogs.msdn.com/b/windowsazurestorage/archive/2015/09/02/issue-in-azure-storage-client-library-5-0-0-and-5-0-1-preview-in-appendblob-functionality.aspx sehen.)

Wie dem auch sei fixiert ich das Problem mit Hilfe der AppendBlock varient statt AppendText wie hier vorgeschlagen:

https://azurekan.wordpress.com/2015/09/08/issues-with-adding-text-to-azure-storage-append-blob/

Die zu der appendtext-Methode wechseln, die den oben definierten Komponententest besteht

0

Warum rufen Sie cab.CreateOrReplace() auch parallel an? Sie sollten es nach test_append_text_concurrency() vor Parallel.Invoke() verschieben

+0

Mit der AzureBlobStorage müssen Sie erstellen, bevor Sie darauf schreiben können. Da ich zum Beispiel Protokolldatei-Blobs basierend auf dem Tag erzeuge, muss ich sicher sein, dass das createorreplace beendet ist, wenn das Blob nicht existiert. Ich wollte das auch auf Nebenläufigkeit testen. – James

+0

Ich bin nicht sicher, dass CreateOrReplace() gleichzeitig ist. Hast du überprüft? – Slava

+0

Weder war ich! daher der Test. Der obige Komponententest kommt über diesen Punkt hinaus, nachdem ich die Zugriffsbedingung und den Ausnahmefang hinzugefügt habe. – James

0

Für Menschen, die eine allgemeinere Lösung für dieses Problem benötigen, habe ich eine Erweiterungsmethode:

public static async Task AppendTextConcurrentAsync(this CloudAppendBlob appendBlob, string content) 
{ 
    using (var stream = new MemoryStream(Encoding.UTF8.GetBytes(content))) 
    { 
     await appendBlob.AppendBlockAsync(stream); 
    } 
} 

Diese Lösung ist mehr im Einklang mit, wie Sie verwenden, um andere Append* Methoden auf CloudAppendBlob.

-1

Sie könnten AppendTextAsync versuchen. Das schien mir in einer ähnlichen Situation zu funktionieren. Die Verwendung des Schlüsselwortes lock könnte ebenfalls funktionieren.

public void Log(string message) 
{ 
    lock (this.appendBlob) 
    { 
     appendBlob.AppendText(string.Format("[{0:s}] {1}{2}", DateTime.Now, message, Environment.NewLine)); 
    } 
} 
+0

Mit 'lock' werden die Anhänge serialisiert, anstatt sie wie vom OP vorgesehen parallel laufen zu lassen. Außerdem habe ich das gleiche Problem wie das OP mit 'AppendTextAsync'. –

Verwandte Themen