我尝试使用新的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个日志,如果日志会在没有警告的情况下丢失,那将是非常不可靠的。
非常感谢任何想法或反馈。
答案 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();