it-swarm.dev

Hintergrundaufgaben auf einer großen Site bearbeiten

Wir haben es mit einem interessanten Problem bei StackOverflow zu tun.

Wir haben eine ganze Reihe kleiner Aufgaben, die "bald erledigt werden müssen". Ein Beispiel ist das Aktualisieren von Listen "Verwandte Fragen". In der Vergangenheit haben wir diese Aufgaben auf die Seitenladevorgänge einiger Benutzer übertragen.

Das war nie ideal, aber es war nicht wirklich auffällig. Nachdem SO das 1.000.000-Fragezeichen überschritten hat, spüren diese unglücklichen Benutzer dies allmählich.

Die natürliche Lösung besteht darin, diese Aufgaben tatsächlich in den Hintergrund zu rücken. Ich denke darüber nach, es gibt zwei Möglichkeiten, dies zu tun.

1. In IIS als benutzerdefinierter Thread-Pool/Work-Queue

Grundsätzlich drehen wir ein paar (nicht - ThreadPool , um IIS nicht zu stören) Threads hoch und lassen sie einige Sammlungen bedienen, in die wir Funcs schieben.

Der große Vorteil hier ist die Einfachheit. Wir müssen uns weder um das Marshalling kümmern noch sicherstellen, dass ein externer Dienst verfügbar ist und reagiert.

Wir erhalten auch Zugriff auf alle unsere gemeinsamen Codes.

Der Nachteil ist, dass wir keine Hintergrund-Threads verwenden sollten. Die mir bekannten Einwände drehen sich alle um das Verhungern IIS (wenn Sie ThreadPool verwenden) und das zufällige Absterben der Threads (aufgrund des AppPool-Recyclings).

Wir haben eine vorhandene Infrastruktur, um den zufälligen Thread-Tod zu einem Nicht-Problem zu machen (die Möglichkeit, eine Aufgabe zu erkennen, wurde im Grunde genommen abgebrochen), und die Begrenzung der Anzahl der Threads (und die Verwendung von Nicht-ThreadPool-Threads) ist ebenfalls nicht schwierig.

Vermisse ich weitere Einwände gegen IIS Thread-Pooling/Work-Queues verarbeiten?

Auf StackOverflow verschoben , da es hier nicht wirklich angesprochen wurde.

2. Als Dienstleistung

Entweder eine Lösung von Drittanbietern oder eine benutzerdefinierte.

Grundsätzlich würden wir eine Aufgabe über die Prozessgrenze hinweg zu einem Dienst zusammenstellen und sie einfach vergessen. Vermutlich verknüpfen wir Code in oder beschränken uns auf unformatiertes SQL + eine Verbindungszeichenfolge.

Der Profi ist, dass es der "richtige Weg" ist, dies zu tun.

Die Nachteile sind, dass wir entweder sehr eingeschränkt sind, was wir tun können, oder dass wir ein System ausarbeiten müssen, um diesen Service mit unserer Codebasis synchron zu halten. Wir müssen auch alle unsere Überwachungs- und Fehlerprotokollierungen irgendwie einbinden, die wir mit der Option "In IIS" kostenlos erhalten.

Gibt es weitere Vorteile oder Probleme mit dem Service-Ansatz?

Kurz gesagt, gibt es unvorhergesehene und unüberwindbare Probleme, die Ansatz Nr. 1 unbrauchbar machen, und wenn ja, gibt es gute Dienste von Drittanbietern, die wir nach Ansatz Nr. 2 prüfen sollten?

49
Kevin Montrose

Vor ein paar Wochen habe ich eine ähnliche Frage auf SO gestellt. Kurz gesagt, mein Ansatz besteht seit einiger Zeit darin, einen Windows-Dienst zu entwickeln. Ich würde NServiceBus (im Wesentlichen MSMQ unter dem Deckmantel) verwenden, um Anfragen von meiner Web-App an meinen Dienst zu leiten. Früher habe ich WCF verwendet, aber eine verteilte Transaktion über WCF richtig funktionieren zu lassen, schien mir immer ein Ärgernis zu sein. NServiceBus hat den Trick gemacht, ich konnte Daten festschreiben und Aufgaben in einer Transaktion erstellen und musste mir keine Sorgen machen, ob mein Dienst zu diesem Zeitpunkt betriebsbereit war. Als einfaches Beispiel, wenn ich jemals eine E-Mail senden musste (zum Beispiel eine Registrierungs-E-Mail), würde ich das Benutzerkonto erstellen und in einer Transaktion ein Signal an meinen Windows-Dienst (zum Senden der E-Mail) auslösen. Der Nachrichtenhandler auf der Serviceseite würde die Nachricht abholen und entsprechend verarbeiten.

Seit ASP .NET 4.0 und AppFabric wurden veröffentlicht) gibt es eine Reihe praktikabler Alternativen zu dem oben genannten Mechanismus. Unter Bezugnahme auf die oben erwähnte Frage haben wir jetzt AppInitialize von AppFabric (über das Netz). Pipe) sowie ASP .NET 4.0 Auto-Start-Funktion, die die Entwicklung von Windows-Diensten als Webanwendungen zu einer praktikablen Alternative macht. Ich habe jetzt aus einer Reihe von Gründen damit begonnen (der größte) Einsatz ist kein Schmerz mehr im Arsch):

  1. Sie können eine Web-Benutzeroberfläche über Ihren Dienst entwickeln (da dieser als Web-App ausgeführt wird). Dies ist äußerst nützlich, um zu sehen, was zur Laufzeit passiert.
  2. Ihr Bereitstellungsmodell für Ihre Webanwendungen funktioniert für Ihre Dienstanwendung.
  3. IIS bietet einige nützliche Funktionen zur Behandlung von Anwendungsfehlern (in mancher Hinsicht ähnlich wie bei einem Windows-Dienst).
  4. Webentwickler sind (natürlich) mit der Entwicklung von Web-Apps sehr vertraut. Die meisten wissen nicht viel über bewährte Methoden bei der Entwicklung eines Windows-Dienstes.
  5. Es bietet eine Reihe von Alternativen zum Bereitstellen einer API für andere Apps.

Wenn Sie diesen Weg gehen (verzeihen Sie mir das Kopieren und Einfügen aus meinem ursprünglichen Beitrag), würde ich definitiv in Betracht ziehen, die Hintergrundlogik in einer separaten Webanwendung auszuführen. Dafür gibt es mehrere Gründe:

  1. Sicherheit . Möglicherweise gibt es ein anderes Sicherheitsmodell für die Benutzeroberfläche, in dem Informationen zu den ausgeführten Hintergrundprozessen angezeigt werden. Ich möchte diese Benutzeroberfläche nur dem Ops-Team zugänglich machen. Die Webanwendung kann auch als ein anderer Benutzer ausgeführt werden, der über erhöhte Berechtigungen verfügt.
  2. Wartung . Es wäre großartig, Änderungen an der Anwendung bereitstellen zu können, in der die Hintergrundprozesse gehostet werden, ohne dass dies Auswirkungen auf die Benutzer hat, die die Front-End-Website verwenden.
  3. Leistung . Wenn die Anwendung von der Hauptwebsite getrennt ist, die Benutzeranforderungen verarbeitet, bedeutet dies, dass Hintergrundthreads die Fähigkeit von IIS, die Warteschlange für eingehende Anforderungen zu verarbeiten, nicht beeinträchtigen. Darüber hinaus kann die Anwendung, die die Hintergrundaufgaben verarbeitet, bei Bedarf auf einem separaten Server bereitgestellt werden.

Dadurch wird auf den Marshalling-Aspekt zurückgegriffen. WCF, NServiceBus/RabbitMQ/ActiveMQ usw., Vanilla MSMQ, RESTful API (Think MVC) sind alle Optionen. Wenn Sie Windows Workflow 4.0 verwenden, können Sie einen Host-Endpunkt verfügbar machen, den Ihre Webanwendung verwenden kann.

Der Webhosting-Ansatz für Dienste ist für mich noch ziemlich neu. Nur die Zeit wird zeigen, ob er die richtige Wahl war. So weit so gut. Übrigens, wenn Sie AppFabric nicht verwenden möchten (ich konnte es nicht, weil Windows Server Web Edition aus irgendeinem bizarren Grund nicht unterstützt wird), funktioniert die im Beitrag des Gu erwähnte Auto-Start-Funktion gut. Halten Sie sich jedoch von der Datei applicationhost.config fern. Alles in diesem Beitrag kann über die IIS -Konsole (Konfigurationseditor auf der Hauptserverebene) eingerichtet werden.

Hinweis: Ich hatte ursprünglich ein paar weitere Links in dieser Nachricht gepostet, aber leider ist dies mein erster Beitrag zu diesem Austausch und es wird nur ein Link unterstützt! Es gab im Grunde zwei andere, um sie Google "Tod für Windows-Dienste ... Es lebe AppFabric!" und "Auto-Start-Asp-Net-Anwendungen". Das tut mir leid.

17
Rohland

In Windows gibt es tatsächlich eine dritte Möglichkeit, Hintergrunddienste auszuführen, und diese ist in der UNIX-Welt sehr verbreitet. Der dritte Weg ist ein CRON Job, der einen Teil Ihrer Infrastruktur ausführt. In Windows wird dies als task scheduler Bezeichnet und ist sehr häufig für die planmäßige Ausführung von Code. Um dies zu verwenden, würden Sie eine Befehlszeilen-App erstellen, die nach einem vordefinierten Zeitplan ausgeführt wird. Dies hat den Vorteil, dass Sie sich keine Sorgen machen müssen, wenn der Prozess wie ein Dienst ausgeführt wird. Wenn er aus irgendeinem Grund fehlschlägt, wird er beim nächsten Mal gestartet.

Für das Marshalling bestimmter Aufgaben müssen Sie diese Aufgaben wirklich nur in einem dauerhaften Binärspeicher speichern. Bis die Befehlszeilen-App sie aus dem Speicher auswählt und ausführt. Ich habe dies in der Vergangenheit unter Verwendung der Datenbank Cassandra als Sitzungsstatusanbieter) getan, um Hintergrundaufgaben für bestimmte Benutzer in der Datenbank Cassandra) zu erledigen und dann die zu haben Wählen Sie sie über die Befehlszeile aus und führen Sie sie für den Benutzer aus.

Dies war möglicherweise nicht die typische Marshalling-Lösung, aber es hat für mich sehr gut funktioniert und sich als sehr elegante Lösung herausgestellt, da die geplanten Aufgaben das Herunterfahren und Netzwerkprobleme überstanden haben und jeder Computer die Aufgabe ausführen konnte, da sie zentral ausgeführt wurde gelagert.

Schamlose Werbung, aber dies ist mein Projekt und die Lösung, die ich gerade kurz beschrieben habe, ist, warum ich das Projekt erstellt habe: http://github.com/managedfusion/fluentcassandra/

22
Nick Berardi

Cron + Web App

Dies ist ein kampferprobtes Design, das zusammen mit Ihrer Webfarm horizontal skaliert und sicherstellt, dass Sie das verwenden. Web-Technologie-Stack , den Sie bereits kennen.

So funktioniert das:

  1. Erstellen Sie einen Controller/eine Aktion in Ihrer Webanwendung, um geplante Hintergrundaufgaben zu erledigen. Normalerweise nenne ich meine http://mydomain.com/system/cron.
  2. Aus Sicherheitsgründen sollte diese Aktion nur für authentifizierte IP-Adressen im lokalen Netzwerk gesperrt werden.
  3. Installieren Sie auf einem separaten Computer Wget und richten Sie Scheduled Task ein, damit wget die Ressource aus Schritt 1 abruft. Sie können die Aufgabe so oft ausführen lassen, wie Sie möchten (normalerweise) 30 Sekunden wählen). Vergessen Sie nicht, das entsprechende Cookie-Argument an Wget zu übergeben, damit es sich bei Ihrer Web-App authentifiziert.
  4. Aus Redundanzgründen können Sie auch ein zweites geplantes Wget auf einem zweiten Computer installieren.

Hurra! Jetzt haben Sie eine Route, die alle 30 Sekunden aufgerufen wird. Und wenn die Bearbeitung der Anfrage 5 Minuten dauert, wird es niemanden interessieren, da sie nicht Teil der Seitenanfrage eines Benutzers ist.

Die Aktion cron sieht sehr einfach aus: Er verfügt über eine Liste von Methoden, die auf einer bestimmten Frequenz ausgeführt werden können. Wenn eine Anfrage eingeht, sieht er, ob eine Methode ausgeführt werden muss, und ruft die entsprechende Methode auf. Dies bedeutet, dass Sie den Zeitplan in Ihrer Datenbank steuern können, in der Sie wahrscheinlich bereits viele andere wichtige Konfigurationsdaten für Ihre Site haben.

Noch wichtiger (für Sie) bedeutet dies, dass Ihre Jobs nicht nach einem festen Zeitplan abgerufen werden müssen. Sie können eine beliebige Logik schreiben, um zu bestimmen, wann eine Methode ausgeführt werden soll.

Vor-und Nachteile

  • Sie können bereits sehr gut ASP.NET MVC-Code schreiben. Auf diese Weise können Sie Ihre Hintergrundaufgaben auf derselben Plattform schreiben, auf der Sie den Rest schreiben Ihre Lösung in.
  • Die Aufgaben werden im selben Kontext wie Ihre Webanwendung ausgeführt, sodass Sie den Cache freigeben und den Hilfsprogramm verwenden können bereits vorhandene Methoden .
  • Wenn Sie einen URI mit Lastenausgleich abrufen möchten, sind Ihre Hintergrundaufgaben jetzt auch mit Lastenausgleich versehen.
  • Gleichzeitige Bereitstellung - Sie müssen sich keine Gedanken über die Synchronisierung Ihrer Webanwendung mit Ihrer Hintergrundaufgabenlogik machen, da sich alle in derselben Bereitstellung befinden.
  • Im Laufe der Jahre haben mir einige Leute gesagt, dass dieses Design "stark gekoppelt" ist, aber wenn sie gedrückt werden, können sie nicht artikulieren, warum das eine schlechte Sache ist.

Hinweis: Wenn Sie Fragen oder Bedenken haben, bitte einen Kommentar hinzufügen. Ich arbeite gerne weiter.

10
Portman

Ich habe in meiner aktuellen Anwendung so gut wie alle Möglichkeiten ausprobiert und angewendet. Ich habe damit begonnen, dasselbe zu tun, was Sie derzeit tun, indem ich auf eine Benutzeranforderung zurückgegriffen habe, um die Daten zu füllen und sie dann in Zukunft zwischenzuspeichern. Ich erkannte, dass dies auch eine schlechte Idee war (insbesondere, wenn Sie auf mehrere Webserver skalieren, nehmen mehr Benutzer den Treffer).

Ich hatte auch einen geplanten Job, der auf eine URL in der ASP.NET-App trifft. Dies ist eine anständige Lösung, die jedoch in dem Moment zusammenbricht, in dem Sie über 1 Webserver hinaus skalieren.

Derzeit verwende ich zwei verschiedene Methoden, beide mit Quartz.NET, einer großartigen kleinen Bibliothek. Das erste ist Quartz.NET, das in Bearbeitung mit ASP.NET ausgeführt wird. Es wird in der Datei global.asax eingerichtet und alle paar Minuten ausgeführt. Ich verwende dies, um den ASP.NET-Cache außerhalb des Bandes zu aktualisieren. Dies ist der einzige Grund, warum er als Teil von ASP.NET ausgeführt wird.

Das zweite ist, dass ich eine Bibliothek namens DaemonMaster geschrieben habe, um Quartz.NET zu verpacken - es macht es einfach, ein DLL] in ein Verzeichnis zu legen und es in einem Windows-Dienst ausführen zu lassen. Ich fand, dass es hilft, dies zu vermeiden Einige der nervigen Teile der Arbeit mit einem Windows-Dienst und die Bereinigung der Quartz.NET-API. Einige der Dienste, die über DaemonMaster ausgeführt werden, haben zwei verschiedene Varianten: Die ersten sind Jobs, die jede Nacht oder alle X Minuten ausgeführt werden müssen Andere Jobs arbeiten in einer Warteschlange basierend auf Daten, die von der ASP.NET-Anwendung eingehen. Die ASP.NET-App löscht JSON-Objekte auf RabbitMQ, und die Dienste fragen RabbitMQ ab und verarbeiten dann die Daten.

Auf dieser Grundlage würde ich vorschlagen, dass Sie sich für einen Windows-Dienst entscheiden (und DaemonMaster auschecken) und bei Bedarf eine Warteschlange wie RabbitMQ verwenden, um die Daten von der ASP.NET-App an die Dienste zu übergeben. Dies hat bei all diesen Lösungen am besten funktioniert . Wenn Sie den Cache laden, ist die Ausführung in ASP.NET sinnvoll, ansonsten glaube ich nicht.

7
James Avery

Ich würde es richtig machen und einen Windows-Dienst ausführen lassen, der eine "Warteschlange" überwacht. Ich sage "Warteschlange", weil das Programmieren mit MSMQ dem Stecken heißer Poker in die Augen ähnelt.

Ich habe mich in die Einfachheit von Delayed :: Job in Rails verliebt, und etwas Ähnliches könnte leicht in .NET gemacht werden.

Grundsätzlich fügen Sie jede Art von SomethingOperation hinzu (etwas, das eine Perform() -Methode hat). Serialisieren Sie dann einfach die relevanten Parameter, geben Sie ihr eine Priorität, eine Art Standard-Wiederholungsverhalten und fügen Sie sie in eine Datenbank ein.

Ihr Dienst würde dies nur überwachen und die Jobs in der Warteschlange bearbeiten.

6
Ben Scheirman

Wir waren ziemlich zufrieden mit einem Service Bus/Message Queue/Service-Ansatz. Die grundlegende Architektur ist dies.

Website sendet Nachricht an Warteschlange

bus.Send(new ProjectApproved()); // returns immediately

Windows-Dienst empfängt und verarbeitet Nachrichten in seiner eigenen Zeit

public class DoesSomethingAwesome : ConsumerOf<ProjectApproved>
{
   public void Consume(ProjectApproved Message)
   {
      // Do something "offline"
   }
}

Der Vorteil ist, dass es für den Front-End-Dienst keine Verzögerung gibt, mit der auch Benutzer verbunden sind. Der Windows-Dienst kann heruntergefahren und ohne Unterbrechung des Hauptstandorts aktualisiert werden. Außerdem ist es extrem schnell.

Wenn Sie nicht alle Ihre Daten in der Nachricht speichern können, können Sie sie jederzeit speichern und später abrufen. Ich schlage vor, einen Dokumentenspeichermechanismus wie den folgenden zu verwenden: RavenDB oder MongoDB , bei dem es sehr einfach ist, Ihre Klassen ohne Änderungen zu speichern.

Website sendet Nachricht an Warteschlange

// Save your object
store.Save(completeProject);

// Send a message indicating its ready to be processed
bus.Send(new ProjectApproved() { ProjectId = completeProject.Id });

Windows-Dienst empfängt und verarbeitet Nachrichten in seiner eigenen Zeit

public class DoesSomethingAwesome : ConsumerOf<ProjectApproved>
{
   public void Consume(ProjectApproved Message)
   {
      // Retrieve your object back
      var completeProject = store.Get(Message.ProjectId);
   }
}

Zur Vereinfachung verwenden wir: Rhino ESB und Topshelf . Die Konfiguration ist äußerst einfach und das Einrichten für eine vorhandene Anwendung hat sich als sehr zeitaufwändig erwiesen.

4
Nathan Palmer

Ich bin gespannt, warum eine Kombination aus beidem keine praktikable Option ist. Im Moment lösen Sie Jobs in Seitenaufrufen aus, wobei ein unglücklicher Saft 10 Sekunden darauf wartet, dass die Seite angezeigt wird. Zumindest verstehe ich Ihre derzeitige Methode so.

Die Ausführung dieser Jobs dauert jedoch immer länger, wenn die Site wächst, und Sie möchten die Benutzererfahrung auf der Site nicht beeinträchtigen. Nicht einmal für ein paar (oder vielleicht viele) unglückliche Benutzer im Laufe des Tages, also denken Sie jetzt darüber nach, Jobs im Hintergrund zu planen.

Ich verstehe nicht, warum ein Hintergrundjob, der in regelmäßigen Abständen ausgeführt wird, einen Besucher nicht imitieren kann. Jetzt bin ich kein Windows-Programmierer, aber in der Linux-Welt würde ich einen Cron-Job einrichten, der in regelmäßigen Abständen ausgeführt wird und 2 Codezeilen enthält.

#!/bin/bash
wget -O /dev/null http://stackoverflow.com/specially_crafted_url

Es kombiniert die Vorteile beider Systeme. Es ist im Hintergrund gemacht. Es wirkt sich nicht auf Benutzer aus. Es wird weiterhin eine Seitenansicht verwendet, um den Job zu starten. Ich habe diesen Ansatz schon einmal gesehen. Es ist in der Regel der Mittelweg zwischen den einfachen Wegen der alten und den komplexeren Wegen, die die Straße hinunterkommen.

pdate

Ich denke, Sie können das Problem des Lastausgleichs umgehen, indem Sie die Jobrunner auf den Webservern selbst ausführen. Der Job Runner zieht eine URL aus der Jobwarteschlange und führt sie folgendermaßen aus:

wget -O /dev/null http://localhost/specially_crafted_url

Aufgrund der Art der Job-/Messaging-Warteschlangen werden die Jobs gleichmäßig auf die Jobläufer verteilt, was bedeutet, dass die special_crafted_url schließlich auf Ihre Webserver verteilt wird.

3
mellowsoon

Ich denke, der Nachteil des reinen Service-Ansatzes besteht darin, dass Sie Code in den Service und von der Kern-App entfernt haben.

Folgendes haben wir mit nicht zeitkritischen Jobs im Hintergrund gemacht, die den Code zusammenhalten und den Service vereinfachen:

  1. Erstellen Sie eine Jobwarteschlange (entweder im Arbeitsspeicher oder in der Datenbank, unabhängig davon, welche Persistenz für die Jobtypen erforderlich ist).
  2. Erstellen Sie einen Webdienst, der die Jobs in der Warteschlange ausführt
  3. Die Dead Simple Service App, die den Webdienst in einem bestimmten Intervall aufruft, überlässt alle komplexen Aufgaben (Abrufen und Ausführen von Jobs) dem Webdienst in Ihrer Kerncodebasis.

Noch einfacher ist es, den Anruf in einer Konsolen-App zu tätigen und ihn mit Task Scheduler oder VisualCron in einen "Dienst" zu verwandeln.

2
Brandon

Resque ist schön. Oder sogar Kthxbye , wenn Sie nach Abschluss über den resultierenden Wert informiert werden müssen.

Beide Redis/Ruby basierten tho.

Ehrlich gesagt, wenn Sie einen service-basierten Ansatz verfolgen, muss dieser nicht unbedingt in Ihre aktuelle Plattform integriert werden, was meiner Meinung nach ein Plus ist. Ich würde hoffen, dass es sich um ein Set-and-Forget-System handelt, das (mit irgendeiner Art von Überwachung) ausgeführt und Aufträge abgeschlossen wird. Ich bin nicht sicher, ob es überhaupt auf derselben Plattform ausgeführt werden muss, da es nur Datenbankinformationen aktualisiert/ändert.

Ich bin mir ziemlich sicher, dass Sie mit viel mehr für viel weniger davonkommen könnten, wenn Sie diese Art von Arbeit auf eine separate Entität übertragen würden, zumal es so aussieht, als würden Sie sich mit Threading-Problemen befassen. Sowohl Resque als auch Kthxbye verschieben die Verarbeitung in separate Prozesse, damit das Betriebssystem die Parallelität verarbeiten kann.

Resque

Kthxbye

1
Lukas

Ich mochte TopShelf. Bewahrt die Einfachheit und führt sie dennoch ordnungsgemäß als Windows-Dienst aus. Erstellen Sie im Grunde eine Konsolen-App, fügen Sie etwa 15 bis 20 Codezeilen hinzu und installieren Sie sie dann als Dienst.

http://code.google.com/p/topshelf/

1
Shane

Wie wäre es mit einem sehr einfachen Windows-Dienst, der auf dem Webserver ausgeführt wird und regelmäßig auf eine Wartungs-URL zugreift, die Ihre verschiedenen Aufgaben erledigt. Lassen Sie es drosseln, wie viel Arbeit es in einer bestimmten Anfrage leistet.

1
Rob Sobers

Ich werde mich hier dem offensichtlichen Trend widersetzen und vorschlagen, das In-IIS-Modell zu wählen. Ich habe es selbst benutzt und es funktioniert wirklich gut. Es ist wirklich nicht so schwer, eine anständige Thread-Pool-Klasse zu implementieren (im Laufe der Jahre habe ich meine Thread-Pool-Klasse erweitert, um die dynamische Erstellung und Zerstörung von Threads, das Wiederholen von Jobs usw. zu unterstützen). Vorteile sind:

  • Kein externer Dienst zu überwachen
  • Einfache Implementierung: kein prozessübergreifendes Marshalling, keine erweiterte Jobüberwachung
  • Sie befinden sich immer noch in Ihrem IIS -Prozess, sodass Sie alle üblichen Protokollierungen usw. durchführen können (keine Notwendigkeit für mehrere Protokolldateien).
  • Sehr vereinfachte Bereitstellung (wenn Sie einen Dienst aktualisieren, müssen Sie den Dienst beenden, die Dateien kopieren, den Dienst starten - dies gilt zusätzlich zu Ihren üblichen Aktualisierungen des Website-Codes)

Meiner Meinung nach ist eine In-IIS-Lösung einfach der "nächste Schritt", um die Arbeit auf zufällige Seitenaufrufe zu übertragen.

1
Dean Harding

Task Queue Java API-Übersicht

Aufgabenkonzepte
In der Hintergrundverarbeitung von App Engine ist eine Aufgabe eine vollständige Beschreibung einer kleinen Arbeitseinheit. Diese Beschreibung besteht aus zwei Teilen:

  • Eine Datennutzlast, die die Aufgabe parametrisiert.
  • Code, der die Aufgabe implementiert.

Aufgaben als Offline-Web-Hooks
Glücklicherweise bietet das Internet bereits eine solche Lösung in Form einer HTTP-Anfrage und ihrer Antwort. Die Datennutzlast ist der Inhalt der HTTP-Anforderung, z. B. Webformularvariablen, XML, JSON oder codierte Binärdaten. Die Code-Referenz ist die URL selbst; Der eigentliche Code ist die Logik, die der Server bei der Vorbereitung der Antwort ausführt.

0
antony.trupe

Ich würde einen WAS-gehosteten WCF-Dienst verwenden, der eine MSMQ-Warteschlange abhört.

Profis

  • Feuern Sie Einwegnachrichten aus der Web-App ab und vergessen Sie sie

  • MSMQ/WCF-Drosselung und erneuter Versuch

  • Garantierte Lieferung; D.

  • Dead Letter Management

  • Verteilte Verarbeitung

  • WAS/MSMQ-Aktivierung

Con's

  • MSMQ (es ist noch nicht tot ...)

Die MSMQ-Funktionen in WCF machen die Verwendung von MSMQ wirklich schön. Ja, Sie werden bei der Konfiguration bluten, aber die Vorteile überwiegen das Opfer.

0
Adam

Ich bin ein paar Mal darauf gestoßen, als ich Webanwendungen entwickelt habe. Wir haben es gelöst, indem wir eine Windows-Konsolenanwendung erstellt haben, die die Aufgabe ausführt, und eine geplante Aufgabe erstellt haben, die von Zeit zu Zeit ausgeführt wird, um die Aufgabe tatsächlich auszuführen.

0

Sie können die Arbeit an einem Hintergrundthread (oder vielen Hintergrundthreads) mit Rx und so ähnlichem umleiten:

var scheduler = new EventLoopScheduler( SchedulerThreadName );
_workToDo = new Subject<Action>();
var queueSubscription = _workToDo.ObserveOn( scheduler ).Subscribe( work => work() );
_cleanup = new CompositeDisposable( queueSubscription, scheduler );

Benutzen:

var work = () => { ... };
_workToDo.OnNext( work ); // Can also put on error / on complete in here

Hosten Sie all das in einer Klasse, von der es immer nur eine gibt (auch bekannt als Singleton, aber machen Sie es richtig - verwenden Sie Ihren IoC-Container, um den Lebensstil zu bestimmen).

Sie können die Größe des Thread-Pools usw. steuern, indem Sie anstelle des EventLoopScheduler (der einen einzelnen Thread ausführt) einen benutzerdefinierten Scheduler schreiben.

0
Neal

Tue beides

Fügen Sie dem Fragenpfad einen optionalen Parameter hinzu, der die Arbeit erledigt, die Sie derzeit auf Benutzeranforderungen ausführen:

Hintergrundaufgaben auf einer großen Site bearbeiten

Erstellen Sie eine Konsolen-App, die auf jedem Server ausgeführt wird und die gemeinsam genutzte Binärdatei IIS log) öffnet und bis zum aktuellen Ende der Datei liest. Verwenden Sie einen Dateisystemwatcher oder ein zeitgesteuertes Intervall zum Vorlesen, um Aktualisierungen als zu sammeln IIS hat das Protokoll geleert.

Verwenden Sie diese Informationen, um festzustellen, welche Seiten aktuell angezeigt wurden.

Verwenden Sie die Seiten-URLs aus dem analysierten Protokoll, um die "Extrastuff" -Version der URL auf localhost mit einem Webclient-Objekt aufzurufen.

Fügen Sie Code hinzu, um die Dateien am Ende jeder Protokollperiode zu wechseln, oder starten Sie den Prozess in jeder Protokollperiode neu.

0
Bill

Ich habe so etwas ein paar Mal implementiert. Unter Windows habe ich ein Befehlszeilenprogramm python] eingerichtet, das zu verschiedenen Zeiten etwas ausführt. Dieses Programm stellt auch eine xmlrpc-Schnittstelle an einem Port zur Verfügung. Anschließend wird jede Minute ein Job mit geplanten Aufgaben ausgeführt fragt die xmlrpc-Schnittstellen ab. Wenn sie nicht aktiv sind, wird versucht, sie zu starten. Wenn dies nicht möglich ist, werden mir E-Mails gesendet.

Der Vorteil ist, dass der ausgeführte Job nicht an Cron oder Zeitplan gebunden ist. Ich habe einen Prozessjob, der alle Sekunden ausgeführt wird, aber zwischen dem Starten eines neuen Jobs immer länger wartet, je nachdem, ob Arbeit zu erledigen war. Es kann auch verwendet werden, um basierend auf dem Ergebnis intelligent zu handeln. Haben Sie einen Fehler von 500? Hast du eine wirklich lange Verspätung? Mach etwas anderes. Benachrichtigen Sie einen anderen Dienst. Usw.

Und das gleiche System funktioniert unter Unix mit geringfügigen Änderungen.

0

Ich habe selbst keine Antwort für dich, aber das Problem hat geklingelt - ich erinnere mich an einige zufällige Typen die einmal in einem Podcast besprochen wurden .

Spolsky: Mir ist aufgefallen, dass eine der Fragen, die Sie im Blog gestellt haben, war, wie Sie mit wiederkehrenden Wartungsaufgaben im Allgemeinen umgehen sollen.

Atwood: Ja.

Spolsky: Ist das eine faire Charakterisierung? Jede Website hat einige Aufgaben, die Sie zum Zeitpunkt des Ladens einer Webseite nicht ausführen möchten, die Sie jedoch mit einer Wiederholung ausführen möchten.

Atwood: Ja, Hintergrundaufgaben.

Spolsky: Ja, was hast du herausgefunden?

Atwood: Nun, ich habe ursprünglich auf Twitter gefragt, weil ich nur etwas Leichtes wollte. Ich wollte wirklich keinen Windows-Dienst schreiben. Ich hatte das Gefühl, dass der Bandcode nicht stimmt. Außerdem ist der Code, der die Arbeit tatsächlich erledigt, tatsächlich eine Webseite, da für mich eine logische Arbeitseinheit auf einer Website eine Webseite ist. Es ist also wirklich so, als würden wir auf die Website zurückrufen. Es ist wie eine weitere Anfrage auf der Website. Ich habe sie als etwas angesehen, das inline bleiben sollte, und als den kleinen Ansatz, den wir auf Twitter gefunden haben Um im Wesentlichen etwas mit einem festen Ablauf zum Anwendungscache hinzuzufügen, haben Sie einen Rückruf. Wenn dieser abläuft, ruft er eine bestimmte Funktion auf, die die Arbeit erledigt, und fügen ihn dann mit demselben Ablauf wieder zum Cache hinzu. Also, es ist ein bisschen, vielleicht ist "Ghetto" das richtige Wort.

0
Oddthinking