使用AppendTextAsync附加到Azure附加Blob导致缺少数据

时间:2015-10-12 19:41:55

标签: azure azure-storage azure-storage-blobs

我尝试使用新的Azure追加blob和Azure Storage SDK 6.0.0在Azure中为应用程序创建记录器。因此,我创建了一个快速测试应用程序,以便更好地了解追加blob及其性能特征。

我的测试程序只循环100次,并在追加blob上附加一行文字。如果我使用同步AppendText()方法一切正常,但是,它似乎仅限于每秒写5-6个附加。所以我试图使用异步AppendTextAsync()方法;但是,当我使用这个方法时,循环运行得更快(如预期的那样),但附加的blob缺少大约98%的附加文本而没有抛出任何异常。

如果我在每次追加操作之间添加Thread.Sleep并休眠100毫秒,我最终会得到大约50%的数据。睡眠1秒钟,我得到所有数据。

这似乎与v5.0.0中发现但在v5.0.2中修复的问题类似:https://github.com/Azure/azure-storage-net/releases/tag/v5.0.2

如果您想尝试重现此问题,请参阅我的测试代码:

static void Main(string[] args)
{
    var accountName = "<account-name>";

    var accountKey = "<account-key>;

    var credentials = new StorageCredentials(accountName, accountKey);

    var account = new CloudStorageAccount(credentials, true);

    var client = account.CreateCloudBlobClient();

    var container = client.GetContainerReference("<container-name>");

    container.CreateIfNotExists();

    var blob = container.GetAppendBlobReference("append-blob.txt");

    blob.CreateOrReplace();

    for (int i = 0; i < 100; i++)
        blob.AppendTextAsync(string.Format("Appending log number {0} to an append blob.\r\n", i));

    Console.WriteLine("Press any key to exit.");

    Console.ReadKey();
}

有没有人知道我是否在尝试将文字行追加到追加blob时做错了什么?否则,任何想法为什么这会丢失数据而不抛出某种异常?

我真的很想开始使用它作为我的应用程序日志的存储库(因为它主要是为此目的而创建的)。但是,如果日志记录率超过每秒5-6个日志,如果日志会在没有警告的情况下丢失,那将是非常不可靠的。

非常感谢任何想法或反馈。

2 个答案:

答案 0 :(得分:6)

我现在有一个基于@ ZhaoxingLu-Microsoft提供的信息的工作解决方案。根据API文档,AppendTextAsync()方法只应在单写程序方案中使用,因为API在内部使用append-offset条件头来避免在多写程序方案中不起作用的重复块。

以下是指定此行为的文档是按设计的: https://msdn.microsoft.com/en-us/library/azure/mt423049.aspx

因此,解决方案是使用AppendBlockAsync()方法。以下实现似乎正常工作:

for (int i = 0; i < 100; i++)
{
    var message = string.Format("Appending log number {0} to an append blob.\r\n", i);

    var bytes = Encoding.UTF8.GetBytes(message);

    var stream = new MemoryStream(bytes);

    tasks[i] = blob.AppendBlockAsync(stream);              
}

Task.WaitAll(tasks);

请注意,我没有在此示例中明确部署内存流,因为该解决方案需要在using块中使用带有async / await的using块,以便在处置之前等待async append操作完成内存流......但这会导致一个完全不相关的问题。

答案 1 :(得分:2)

您错误地使用了async方法。 blob.AppendTextAsync()是非阻塞的,但它返回时并没有真正完成。在退出流程之前,您应该等待所有async任务。

以下代码是正确的用法:

var tasks = new Task[100];
for (int i = 0; i < 100; i++)
    tasks[i] = blob.AppendTextAsync(string.Format("Appending log number {0} to an append blob.\r\n", i));

Task.WaitAll(tasks);

Console.WriteLine("Press any key to exit.");

Console.ReadKey();