2015-09-11 36 views
6

Hiểu biết của tôi là Azure CloudAppendBlob đã an toàn khỏi các vấn đề tương tranh vì bạn chỉ có thể thêm vào bộ nhớ blob này và không cần so sánh các thẻ E. Như đã trình bày qua đường bưu điện này:Lỗi Azure CloudAppendBlob với quyền truy cập đồng thời

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

cụ thể:

Bên cạnh đó, Nối Blob hỗ trợ có nhiều khách hàng bằng văn bản cho blob cùng mà không cần phải đồng bộ hóa (không giống như khối và trang blob)

Tuy nhiên, kiểm tra đơn vị sau đây nêu lên:

412 điều kiện vị trí phụ được chỉ định không được đáp ứng.

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 

Đây là bài kiểm tra đơn vị. Có lẽ dịch vụ sẽ xử lý các yêu cầu từ các ngữ cảnh khác nhau nhưng không như thế này là song song?

[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")); 
    } 

Phương pháp trong 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);  
    } 

Có lẽ tôi đang thiếu một cái gì đó. Lý do tôi đang cố gắng để làm điều này là tôi có nhiều công việc web mà tất cả có thể viết cho phụ này blob và tôi figured đây là những gì nó được thiết kế cho?

+0

Tôi cũng vừa thử nghiệm điều này từ quay lên nhiều webjob và viết một số văn bản vào cùng một appendblob. Tôi nhận được lỗi tương tự. – James

+0

Lưu ý rằng tôi đang sử dụng phiên bản 5.0.2.0 của Microsoft.WindowsAzure.Storage (Tôi cũng đã thử chống lại bản xem trước 5.0.3.0) – James

Trả lời

5

Sau một chút tìm kiếm, có vẻ như đây là vấn đề thực tế.

Tôi đoán AppendBlobStorage khá mới. (Ngoài ra còn có các vấn đề khác tại thời điểm với AppendBlobStorage thấy

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.)

Dù sao tôi cố định vấn đề này bằng cách sử dụng các varient AppendBlock hơn AppendText như đề xuất ở đây:

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

Các thay đổi phương thức appendtext vượt qua bài kiểm tra đơn vị được xác định ở trên

public void AppendText(string filename, string text) 
    { 
     if (string.IsNullOrWhiteSpace(filename)) 
      throw new ArgumentException("filename cannot be null or empty"); 

     if (!string.IsNullOrEmpty(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 (StorageException) { } 
      } 

      // use append block as append text seems to have an error at the moment. 
      using (MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(text))) 
      { 
       cab.AppendBlock(ms); 
      } 
     } 

    } 
0

Tại sao bạn gọi cab.CreateOrReplace() cũng song song? Bạn nên chuyển nó đến test_append_text_concurrency() trước Parallel.Invoke()

+0

Với AzureBlobStorage bạn phải tạo trước khi có thể ghi vào đó. Kể từ khi tôi tạo ra các blob tập tin đăng nhập dựa trên ngày ví dụ tôi cần phải chắc chắn rằng các createorreplace được thực hiện nếu blob không tồn tại. Tôi cũng muốn thử nghiệm điều này cho đồng thời. – James

+0

Tôi không chắc chắn CreateOrReplace() là đồng thời. Bạn đã kiểm tra chưa? – Slava

+0

Tôi cũng vậy! do đó thử nghiệm. Các bài kiểm tra đơn vị trên được vượt qua điểm đó ok sau khi tôi thêm điều kiện truy cập và bắt ngoại lệ. – James

0

Đối với những người cần một giải pháp chung chung hơn cho vấn đề này, tôi đã tạo ra một phương pháp khuyến nông:

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

Giải pháp này là phù hợp hơn với cách bạn sử dụng các phương pháp khác Append* trên CloudAppendBlob.

-1

Bạn có thể thử AppendTextAsync. Điều đó dường như làm việc cho tôi trong một tình huống tương tự. Sử dụng từ khóa khóa cũng có thể hoạt động.

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

Sử dụng 'khóa' sẽ tuần tự hóa các phụ thêm thay vì cho phép chúng chạy song song như dự định của OP. Ngoài ra, tôi đã gặp phải vấn đề tương tự như OP với 'AppendTextAsync'. –

Các vấn đề liên quan