2017-06-16 58 views
0

我們的服務位於GatewayServer後面。如果下游依賴關係返回適當的響應代碼並取決於它可能重試的網關服務器上設置的超時時間,則網關服務器會自行應用重試。Azure存儲響應代碼429

通過它看來,存儲客戶端不會從該頁面返回一個429響應,明顯的Azure存儲文檔狀況:

https://docs.microsoft.com/en-us/rest/api/storageservices/table-service-error-codes

https://docs.microsoft.com/en-us/azure/storage/storage-performance-checklist

從上面的鏈接的重試次數科: 在某些情況下,存儲服務可能會限制您的應用程序,或者由於某些瞬態條件而可能無法提供請求,並返回「503服務器忙」消息或「500超時」。客戶端庫知道哪些錯誤是可重試的,哪些不是。

由於Storage Client庫不返回429,我們無法決定是否嘗試重試?重要的是如何確定給定的5xx錯誤是否可以在我們的端重試,以便我們不會重試並返回429到重試所有這些請求的網關服務器?我們的想法是,我們希望避免在不同層上重試,並讓網關服務器根據下游服務的響應和超時設置做出決定。

是否有一個標題或特定的錯誤信息,我們可以作出這個決定?

回答

0

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