伟大的问题!他们关键的一点是,Storage Service本身不会重试失败的操作。对于每个操作,服务将简单地返回一个HTTP状态码。 Onus依赖客户端来推断这些状态码并在需要时执行重试。
如果我们以.Net存储客户端库为例,有一个内置的重试机制可以拦截错误代码并执行重试。如果我没有弄错,默认的重试机制是Exponential Retry
。
但是,您可以编写自己的重试逻辑并将其注入代码中。每当发生错误时,您的重试逻辑就会到位,请求将被重试。
前段时间我在这个话题上写了一篇博客文章,您可能会觉得有用:http://gauravmantri.com/2012/12/30/storage-client-library-2-0-implementing-retry-policies/。我意识到这是一个非常古老的帖子,很多已经改变了,但是应该给你一些关于如何实现你自己的重试策略的想法。
在这篇博客文章中,我写了一些示例代码,它将在您删除容器并立即通过相同名称创建新容器时进行重试。由于删除容器可能需要一些时间,所以在正常情况下,您将从默认不可重试的服务中收回409个错误代码。但是,通过这个自定义重试策略,您的代码将在放弃之前重试创建blob容器“x”次。
public class ContainerBeingDeletedRetryPolicy : IRetryPolicy
{
int maxRetryAttemps = 10;
TimeSpan defaultRetryInterval = TimeSpan.FromSeconds(5);
public ContainerBeingDeletedRetryPolicy(TimeSpan deltaBackoff, int retryAttempts)
{
maxRetryAttemps = retryAttempts;
defaultRetryInterval = deltaBackoff;
}
public IRetryPolicy CreateInstance()
{
return new ContainerBeingDeletedRetryPolicy(TimeSpan.FromSeconds(2), 5);
}
public bool ShouldRetry(int currentRetryCount, int statusCode, Exception lastException, out TimeSpan retryInterval, OperationContext operationContext)
{
retryInterval = defaultRetryInterval;
if (currentRetryCount >= maxRetryAttemps)
{
return false;
}
//Since we're only interested in 409 status code, let's not retry any other operation.
if ((HttpStatusCode)statusCode != HttpStatusCode.Conflict)
{
return false;
}
//We're only interested in storage exceptions so if there's any other exception, let's not retry it.
if (lastException.GetType() != typeof(StorageException))
{
return false;
}
else
{
var storageException = (StorageException)lastException;
string errorCode = storageException.RequestInformation.ExtendedErrorInformation.ErrorCode;
if (errorCode.Equals("ContainerBeingDeleted"))
{
return true;
}
else
{
return false;
}
}
return true;
}
}
这里是一个使用这个重试策略代码:
static string accountName = "<storage account name>";
static string accountKey = "<storage account key>";
static void Main(string[] args)
{
var storageAccount = new CloudStorageAccount(new StorageCredentials(accountName, accountKey), true);
string blobContainerName = "temp-" + DateTime.UtcNow.Ticks;
CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();
IRetryPolicy linearRetryPolicy = new LinearRetry(TimeSpan.FromSeconds(2), 10);
blobClient.RetryPolicy = linearRetryPolicy;
CloudBlobContainer blobContainer = blobClient.GetContainerReference(blobContainerName);
blobContainer.Create();
Console.WriteLine("Blob container created.");
blobContainer.Delete();
Console.WriteLine("Blob container deleted.");
IRetryPolicy containerBeingDeletedRetryPolicy = new ContainerBeingDeletedRetryPolicy(TimeSpan.FromSeconds(2), 10);
BlobRequestOptions requestOptions = new BlobRequestOptions()
{
RetryPolicy = containerBeingDeletedRetryPolicy,
};
blobContainer.Create(requestOptions);
Console.WriteLine("Blob container created.");
Console.ReadLine();
}