首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用AppendTextAsync追加到Azure附加Blob会导致数据丢失

使用AppendTextAsync追加到Azure附加Blob会导致数据丢失
EN

Stack Overflow用户
提问于 2015-10-12 19:41:54
回答 2查看 3.4K关注 0票数 3

我试图使用新的Azure附加blobs和Azure Storage 6.0.0为Azure中的应用程序创建一个记录器。因此,我创建了一个快速测试应用程序,以更好地理解附加的blobs及其性能特性。

我的测试程序简单地循环了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

这是我的测试代码,如果您想要重现这个问题的话:

代码语言:javascript
复制
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个日志,那将是非常不可靠的。

如有任何想法或反馈,将不胜感激。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2015-10-13 18:09:42

我现在有一个工作解决方案,基于@肇星路-微软提供的信息。根据API文档,AppendTextAsync()方法只应在单写入器场景中使用,因为API内部使用附加偏移条件标头以避免重复块,而这些块在多作者场景中不能工作。

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

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

代码语言:javascript
复制
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块内包含一个带有异步/等待的using块,以便在处理内存流之前等待异步附加操作完成.但这导致了一个完全不相关的问题。

票数 7
EN

Stack Overflow用户

发布于 2015-10-13 00:40:09

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

以下代码是正确的用法:

代码语言:javascript
复制
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();
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/33088964

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档