2017-06-16 2 views
0

Wir haben unseren Service, der hinter einem GatewayServer steht. Der Gateway-Server wendet einen Wiederholungsversuch selbst an, wenn die Downstream-Abhängigkeiten einen entsprechenden Antwortcode zurückgeben und abhängig von dem auf dem Gateway-Server festgelegten Timeout einen neuen Versuch starten.Azure Storage Response Code für 429

durch die docs Azure Storage gehen scheint es, dass der Speicher-Client von dieser Seite keine 429 Antwort als evident zurückkehrt:

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

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

Von Retries Abschnitt des obigen Link : In einigen Fällen kann der Speicherdienst Ihre Anwendung drosseln oder die Anforderung aufgrund einer vorübergehenden Bedingung einfach nicht liefern und eine Meldung "503 Server busy" oder "500 Timeout" zurückgeben. Die Client-Bibliotheken wissen, welche Fehler wiederholt werden können und welche nicht.

Da der Speicher-Client-Bibliothek nicht 429 zurückgibt, können wir keine Entscheidung treffen, ob ein erneuter Versuch sollte oder nicht versucht werden? Das Wichtigste ist, wie man feststellen kann, ob ein gegebener 5xx-Fehler an unserem Ende erneut versucht werden kann, so dass wir keinen 429 an den Gateway-Server wiederholen und zurückgeben, der alle derartigen Anfragen wiederholt. Die Idee besteht darin, dass Wiederholungsversuche auf verschiedenen Layern vermieden werden sollen und der Gateway-Server eine Entscheidung treffen muss, die auf der Antwort von den nachgelagerten Diensten und dem gesetzten Timeout basiert.

Gibt es einen Header oder eine bestimmte Fehlermeldung, die wir auf schwenken kann, diese Entscheidung zu treffen?

Antwort

0

Große Frage! Das Wichtigste, was Sie hier verstehen müssen, ist, dass Storage Service selbst keine fehlgeschlagenen Operationen wiederholt. Für jede Operation gibt der Dienst einfach einen HTTP-Statuscode zurück. Onus liegt auf dem Client, um diese Statuscodes abzuleiten und bei Bedarf Wiederholungen durchzuführen.

Wenn wir das Beispiel von Net Storage-Client-Bibliothek nehmen, gibt es einen eingebauten in Wiederholungsmechanismus, die Fehlercodes abfängt und Wiederholungen auszuführen. Wenn ich mich nicht irre, ist der Standardwiederholungsmechanismus Exponential Retry.

Sie können jedoch Ihre eigene Wiederholungslogik schreiben und sie in Ihren Code einfügen. Wann immer ein Fehler auftritt, wird Ihre Wiederholungslogik aktiviert und die Anforderungen werden erneut versucht.

Ich schrieb einen Blog-Post auf diesem Thema vor einiger Zeit, dass Sie nützlich sein können: http://gauravmantri.com/2012/12/30/storage-client-library-2-0-implementing-retry-policies/. Ich weiß, dass es ein ziemlich alter Beitrag ist und vieles hat sich geändert, aber das sollte Ihnen eine Idee geben, wie Sie Ihre eigenen Wiederholungsrichtlinien implementieren können.

In diesem Blog-Post schrieb ich einige Beispiel-Code, die eine Wiederholung tun, wenn Sie einen Container löschen und sofort einen neuen Container mit dem gleichen Namen erstellen. Da das Löschen eines Containers unter normalen Umständen einige Zeit dauern kann, erhalten Sie einen 409-Fehlercode vom Service, der standardmäßig nicht erneut versucht werden kann. Aber mit dieser benutzerdefinierten Wiederholungsrichtlinie wird Ihr Code versuchen, einen Blob-Container für "x" mehrmals zu erstellen, bevor er aufgibt.

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; 
    } 
} 

und hier ist der Code, der diese Wiederholungs Richtlinie verwendet:

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(); 
}