2017-06-16 55 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(); 
}