2015-02-19 11 views
5

ich versuchen, Nachrichten in Azure-Warteschlangen wie folgt asynchron einzureihen:Asynchron zu Azure Queues veröffentlichen

private async Task EnqueueItemsAsync(IEnumerable<string> messages) { 
      var tasks = messages.Select(msg => _queue.AddMessageAsync(new CloudQueueMessage(msg), 
       null, null, null, null)); 

      await Task.WhenAll(tasks); 
     } 

Wenn ich es richtig sagt, das „Start ein Element nach dem anderen Einreihen, ohne sie zu warten, geschrieben werden, halten eine Referenz für jede Aufgabe und dann warten bis alle gepostet werden ".

Dieser Code funktioniert in den meisten Fällen gut, aber für eine große Anzahl von Elementen (5000), es beginnt das Einreihen und dann wirft eine Timeout-Ausnahme (nach ~ 3500 Artikeln Warteschlange gestellt hat).

Ich löste es durch jede mit der nächsten Kann mir jemand erklären, bevor Sie fortfahren, warum geschah ein

private async Task EnqueueItemsAsync(IEnumerable<string> messages) { 
      foreach (var message in messages) { 
       await _queue.AddMessageAsync(new CloudQueueMessage(message), null, null, null, null); 
      } 
     } 

zu beenden wartet das?

Ausnahme:

System.AggregateException, die viele solche Ausnahmen Wraps: Microsoft.WindowsAzure.Storage.Core.Util.AsyncExtensions.<>c__DisplayClass4.<CreateCallbackVoid>b__3(IAsyncResult ar) Informationen anfordern RequestID: RequestDate: Statusmessage: < --- ---> (Interne Ausnahme # 1) zu. StorageException: Der Client konnte den Vorgang nicht innerhalb des angegebenen Zeitlimits abschließen. ---> System.TimeoutException: Der Client konnte die Operation innerhalb des angegebenen Zeitlimits nicht beenden. --- Ende der inneren Ausnahmestapelspur --- Microsoft.WindowsAzure.Storage.Core.Executor.Executor.EndExecuteAsync [T] (IAsyncResult Ergebnis) `.

+0

Welche Linie die Ausnahme auslöst? und welche Methode? Notieren Sie die Ausnahme Name, Nachricht und StackTrace –

+0

@SriramSakthivel danke für die Erwähnung, nur aktualisiert mein Beitrag –

Antwort

6

Eine Warteschlange in Azure hat einen Durchsatz von 2000 Nachrichten pro Sekunde.

See: Azure Storage Scalability and Performance Targets

Wenn Ihre Anwendung die Grenze erreicht von dem, was eine Partition für Ihre Arbeitsbelastung umgehen kann, wird Azure Storage beginnen Fehlercode 503 (Server Busy) oder Fehlercode 500 (zurückkehren Operation Timeout) Antworten. Wenn dies auftritt, sollte die Anwendung eine exponentielle Backoff-Richtlinie für Wiederholungen verwenden. Der exponentielle Backoff ermöglicht es, die Belastung der Partition zu verringern und Spikes im Datenverkehr zu dieser Partition zu verringern.

+0

Danke, ich denke, das löst das Rätsel. Also mein erster Code läuft die for-Schleife in weniger als einer Sekunde, beginnend 5000 Post-Anfragen in weniger als einer Sekunde, die Timeout-Antworten ergibt ... scheint vernünftig –

1

Es scheint, dass man, indem man einen QueryRequestOptions zu AddMessageAsync einen robusteren Mechanismus machen.

Bevor die Abfrage gesendet wird, fügt die Anforderungsnachricht diese Eigenschaften dem Befehl hinzu.

Ich würde versuchen, QueryRequestOptions übergeben und einen Wert auf MaximumExecutionTime und ServerTimeout mit einem größeren Wert einstellen.

Dies ist, wie die Anforderung an vor gefüllt gesendet werden:

// Microsoft.WindowsAzure.Storage.Queue.QueueRequestOptions 
internal void ApplyToStorageCommand<T>(RESTCommand<T> cmd) 
{ 
    if (this.LocationMode.HasValue) 
    { 
     cmd.LocationMode = this.LocationMode.Value; 
    } 
    if (this.ServerTimeout.HasValue) 
    { 
     cmd.ServerTimeoutInSeconds = new int?((int)this.ServerTimeout.Value.TotalSeconds); 
    } 
    if (this.OperationExpiryTime.HasValue) 
    { 
     cmd.OperationExpiryTime = this.OperationExpiryTime; 
     return; 
    } 
    if (this.MaximumExecutionTime.HasValue) 
    { 
     cmd.OperationExpiryTime = new DateTime?(DateTime.Now + this.MaximumExecutionTime.Value); 
    } 
} 

Und das ist, wie es gesendet wird:

rESTCommand.PreProcessResponse = delegate(RESTCommand<NullType> cmd, HttpWebResponse resp, Exception ex, OperationContext ctx) 
{ 
    HttpResponseParsers.ProcessExpectedStatusCodeNoException<NullType>(HttpStatusCode.Created, resp, NullType.Value, cmd, ex); 
    return NullType.Value; 
}; 
+0

Danke, interessante Ansatz, um die Möglichkeit für ein Timeout zu minimieren, aber ich wollte es verstehen was die Zeitüberschreitung verursacht hat. –

Verwandte Themen