2013-02-05 3 views
15

Ich habe eine Webapi, die entwickelt wurde, um Berichte in einer Warteschlange zu verarbeiten. Die Schritte, die Anwendung erfolgt, sind wie folgt:Wie Sie Hintergrundaufgaben in der ASP.NET-Web-API einbinden

  • Receive Inhalt
  • Karte den Inhalt auf ein Objekt und legen sie in die Warteschlange
  • Poll für Elemente in der Warteschlange
  • Prozesselemente in der Warteschlange eine anhängige zu einer Zeit

ich dachte Entity Framework zu verwenden, um eine Datenbank von Warteschlange Elementen zu erstellen, wie zum Beispiel:

Meine Frage

- Gibt es eine effizientere Art und Weise, mit NServiceBus, Blocking oder ConcurrentQeueue, als ständig die Datenbank abfragen, und ziehen Sie die Elemente nacheinander anhängig? Ich habe noch nie Warteschlangen benutzt.

Ein Gedanke ist es, eine Warteschlange von Aufgaben und auf einem separaten Thread-Prozess alle ausstehenden Aufgaben zu erstellen. Etwas ähnlich zu Most efficient way to process a queue with threads, aber ich möchte sicherstellen, dass ich die effizienteste Route gehe.

EDIT: Eine große Frage, die ich hier habe, ist der beste Weg, um den Fortschritt für den Benutzer angezeigt werden soll. Sobald der Benutzer den Inhalt übermittelt hat, wird er auf eine neue Seite geleitet und kann den Status anhand der Stapelkennung anzeigen. Ist MSMQ oder NServiceBus erforderlich, um den Benutzer zu benachrichtigen? Dies scheint eine Variation des REquest/Acknowledge/Push-Paradigmas zu sein.

+0

wäre meine Lösung eine 'Lock' Anweisung um den Teil des Codes, wo Sie in die Datenbank schreiben. – efkah

+0

Danke für den Tipp - hatte nicht daran gedacht, und hätte wahrscheinlich später viele Probleme verursacht :) Irgendwelche Gedanken über die Methode der Warteschlangen? Sollte ich versuchen, eine BlockingCollection oder nur die ständige Abfrage der Datenbank zu versuchen? Aktualisierte die Frage mit einer schnellen Bearbeitung – appsecguy

Antwort

23

IMHO, Ihre ASP.NET-Web-API-Anwendung sollte diese Hintergrundaufgaben nicht selbst ausführen. Es sollte nur dafür verantwortlich sein, die Anfrage zu erhalten, sie in der Warteschlange zu belassen (wie Sie angegeben haben) und die Antwort zurückzugeben, die den Erfolg oder Misserfolg der empfangenen Nachricht anzeigt. Sie können verschiedene Messaging-Systeme wie RabbitMQ für diesen Ansatz verwenden.

Wie für die Benachrichtigung haben Sie ein paar Optionen. Sie können einen Endpunkt haben, den der Client prüfen kann, ob die Verarbeitung abgeschlossen ist oder nicht. Alternativ können Sie einen Streaming-API-Endpunkt bereitstellen, den Ihr Client abonnieren kann. Auf diese Weise muss der Client den Server nicht abfragen. Der Server kann die verbundenen Clients benachrichtigen. ASP.NET Web API bietet eine gute Möglichkeit, dies zu tun. In der folgenden Blog-Post erklärt, wie:

Sie auch SignalR für diese Art von Server-Client-Benachrichtigungen berücksichtigen können.

Der Grund, warum Hintergrund Aufgaben schwer für ASP.NET Web-API-Anwendung ist, dass Sie verantwortlich sind die AppDomain am Leben zu halten. Dies ist besonders beim Hosting unter IIS ein Problem. Die folgenden Blog-Posts erklärt wirklich gut, was ich meine:

+0

Nun, die Hintergrundaufgabe läuft im Wesentlichen mehrere ASP.NET-Funktionen, um einen Bericht automatisch zu generieren. Würden Sie dann eine separate Anwendung empfehlen und den Inhalt an diesen weitergeben? – appsecguy

+1

@ pendraggon87 was meinst du mit "ASP.NET-Funktionen"? – tugberk

+0

Im Wesentlichen empfange ich Inhalt und verwende dann die Interop-Bibliotheken, um ein Word-Dokument zu generieren. Ich hatte eine Webanwendung erstellt, die es den Benutzern ermöglichte, das Dokument nach dem Eingeben vieler Informationen per Knopfdruck zu generieren, aber ich arbeite gerade daran, ein System zu erstellen, in dem ich den Bericht durch den Empfang von JSON-Daten generieren kann. Also habe ich meinen ganzen Code geschrieben, um den Bericht zu schreiben. Empfiehlst du, dass ich diesen Code in eine separate Anwendung lege? – appsecguy

6

Es ist ein NuGet Paket und es HangFire genannt - https://github.com/HangfireIO/Hangfire. Die Aufgaben bleiben auch nach dem Apppool-Recycling bestehen.

+0

danke für diesen Link, ich bin noch nie zuvor darauf gestoßen, könnte aber genau das sein, was ich brauche! – Phil

1

Ich mag @ Todds Lösung. Nur aus Gründen der Vollständigkeit, aber es ist eine andere Option noch nicht erwähnt:

HostingEnvironment.QueueBackgroundWorkItem(cancellationToken => 
{ 
    // Some long-running job 
}); 

Hinweis:

„Wenn ASP.NET zu recyceln hat, wird die Hintergrundarbeit mitteilen (durch eine CancellationToken Einstellung) und wird dann bis zu 30 Sekunden warten, bis die Arbeit abgeschlossen ist. Wenn die Hintergrundarbeit in diesem Zeitrahmen nicht abgeschlossen ist, wird die Arbeit auf mysteriöse Weise verschwinden. "

Und vermeiden Sie Service-Methoden mit einem injizierten DbContext hier, da dies nicht funktioniert.

Quellen: MariusSchulz und StephenCleary

Verwandte Themen