偉大的問題!他們關鍵的一點是,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();
}