Beste Möglichkeit, geplante Aufgaben auszuführen [geschlossen]

229

Heute haben wir eine Konsolenanwendung zum Ausführen der geplanten Aufgaben für unsere ASP.NET-Website erstellt. Aber ich denke, dieser Ansatz ist etwas fehleranfällig und schwer beizubehalten. Wie führen Sie Ihre geplante Aufgabe aus (in einer Windows / IIS / ASP.NET-Umgebung)?

Aktualisieren:

Beispiele für Aufgaben:

  • Senden von E-Mails aus einer E-Mail-Warteschlange in der Datenbank
  • Veraltete Objekte aus der Datenbank entfernen
  • Abrufen von Statistiken aus Google AdWords und Ausfüllen einer Tabelle in der Datenbank.
Niels Bosma
quelle
Was ist ein Beispiel für die Aufgaben, die Sie ausführen?
JeffO
4
Sie müssen atrigger.com
Kousha
Wenn Sie Plesk haben, können Sie ein VBS schreiben und es dem Taskplaner
hinzufügen

Antworten:

74

Alle meine Aufgaben (die geplant werden müssen) für eine Website werden auf der Website gespeichert und von einer speziellen Seite aus aufgerufen. Ich habe dann einen einfachen Windows-Dienst geschrieben, der diese Seite von Zeit zu Zeit aufruft. Sobald die Seite ausgeführt wird, wird ein Wert zurückgegeben. Wenn ich weiß, dass noch mehr Arbeit zu erledigen ist, starte ich die Seite sofort erneut, andernfalls starte ich sie in kurzer Zeit. Dies hat bei mir sehr gut funktioniert und behält meine gesamte Aufgabenlogik mit dem Webcode bei. Vor dem Schreiben des einfachen Windows-Dienstes habe ich die Seite alle x Minuten mit dem Windows-Scheduler aufgerufen.

Eine andere bequeme Möglichkeit, dies auszuführen, ist die Verwendung eines Überwachungsdienstes wie Pingdom . Zeigen Sie mit der http-Prüfung auf die Seite, auf der Ihr Servicecode ausgeführt wird. Lassen Sie die Seite Ergebnisse zurückgeben, die dann verwendet werden können, um Pingdom zum Senden von Warnmeldungen auszulösen, wenn etwas nicht stimmt.

Brettski
quelle
3
Dies ist die Lösung, mit der ich gelandet bin. Anstelle eines benutzerdefinierten Webdienstes verwende ich Windows Scheduler + Curl. Was ist der Vorteil der Verwendung eines Windows-Dienstes?
Niels Bosma
16
Haben Sie sich die Ablauftechnik für Cache-Elemente angesehen? Ich denke, Sie werden feststellen, dass dies eine viel idealere
Richard Clayton
10
Was kann einen böswilligen Benutzer (oder eine Suchmaschinenspinne) davon abhalten, diese Seite aufzurufen und damit Ihre geplanten Aufgaben auszuführen?
UpTheCreek
8
Sie können böswillige Anrufe stoppen, indem Sie einen statischen Zeitstempel in der Web-App speichern und nur ausführen, wenn der Zeitstempel nicht festgelegt wurde (erster Anruf) oder die richtige Zeit seit dem letzten Anruf abgelaufen ist.
Rob Kent
5
Ich stoppe böswillige Anrufe an meine URL, indem ich überprüfe, ob die IP-Adresse eine interne Adresse ist oder nicht. Es gibt nichts zurück und tut nichts, wenn es nicht intern in unserer Organisation ist.
user1408767
128

Diese Technik von Jeff Atwood für Stackoverflow ist die einfachste Methode, die mir begegnet ist. Es basiert auf dem Rückrufmechanismus "Cache-Element entfernt", der in das Cache-System von ASP.NET integriert ist

Update: Stackoverflow ist dieser Methode entwachsen. Es funktioniert nur, während die Website ausgeführt wird, aber es ist eine sehr einfache Technik, die für viele Menschen nützlich ist.

Schauen Sie sich auch Quartz.NET an

BC.
quelle
12
Was passiert also, wenn die Anwendung nicht ausgeführt wird, die geplante Aufgabe jedoch ausgeführt werden muss?
MichaelGG
2
Dies kann auch die Benutzererfahrung verlangsamen, wenn die Ausführung der Aufgabe dieses Mal eine Weile dauert. Ich ziehe es vor, dass der Benutzer meine Wartung / Aufgaben nicht für mich erstellt.
Brettski
5
Das ist höllisch beängstigend! Alles könnte dazu führen, dass die Anwendung nicht mehr ausgeführt wird und wahrscheinlich erst bei der nächsten Benutzeranforderung neu gestartet wird. Zwischen diesen Zeiten werden Ihre Aufgaben nicht ausgeführt!
Dienstag,
43
Etwas, das mir heute in den Kommentaren zum ursprünglichen Blog-Beitrag aufgefallen ist: No, we’ve switched to a dedicated task. We definitely outgrew this technique. I do think it’s fine for small sites though!- Jeff Atwood
Joel Coehoorn
3
-1 Bei diesem Ansatz liegt ein großer Fehler vor. Immer wenn die Anwendung recycelt wird, wird das Ereignis 'CacheItemRemoved' ausgelöst und Ihre geplante Aufgabe wird ausgeführt. Auf Produktionsstätten kann dies einige Male am Tag passieren. Nicht so gut, wenn die Aufgabe wöchentlich ausgeführt werden soll.
Steven de Salas
30

Erstellen Sie einen benutzerdefinierten Windows-Dienst .

Ich hatte einige geschäftskritische Aufgaben als geplante Konsolen-Apps eingerichtet und fand sie schwierig zu warten. Ich habe einen Windows-Dienst mit einem Herzschlag erstellt, der alle paar Minuten einen Zeitplan in meiner Datenbank überprüft. Es hat wirklich gut geklappt.

Trotzdem verwende ich für die meisten meiner unkritischen Wartungsaufgaben weiterhin geplante Konsolen-Apps. Wenn es nicht kaputt ist, reparieren Sie es nicht.

Chris Van Opstal
quelle
7
Zu Ihrer Information, der Link ist jetzt tot.
Charles Burns
1
@ CharlesBurns, Sie können immer tote Links mit archive.org durchsuchen: web.archive.org/web/20090919131944/http://www.dotheweb.net/…
Nikolay Kostov
17

Ich habe festgestellt, dass dies für alle Beteiligten einfach ist:

  • Erstellen Sie eine Webservice-Methode wie DoSuchAndSuchProcess
  • Erstellen Sie eine Konsolen-App, die diese Webmethode aufruft.
  • Planen Sie die Konsolen-App im Taskplaner.

Mit dieser Methode ist die gesamte Geschäftslogik in Ihrer Webanwendung enthalten. Sie haben jedoch die Zuverlässigkeit des Windows-Task-Managers oder eines anderen kommerziellen Task-Managers, um diese zu starten und Rückgabeinformationen wie einen Ausführungsbericht aufzuzeichnen. Die Verwendung eines Webdienstes anstelle der Veröffentlichung auf einer Seite hat einen gewissen Vorteil, da es einfacher ist, Rückgabedaten von einem Webservice abzurufen.

Daniel Auger
quelle
10

Warum das Rad neu erfinden, verwenden Sie die Threading- und die Timer-Klasse.

    protected void Application_Start()
    {
        Thread thread = new Thread(new ThreadStart(ThreadFunc));
        thread.IsBackground = true;
        thread.Name = "ThreadFunc";
        thread.Start();
    }

    protected void ThreadFunc()
    {
        System.Timers.Timer t = new System.Timers.Timer();
        t.Elapsed += new System.Timers.ElapsedEventHandler(TimerWorker);
        t.Interval = 10000;
        t.Enabled = true;
        t.AutoReset = true;
        t.Start();
    }

    protected void TimerWorker(object sender, System.Timers.ElapsedEventArgs e)
    {
        //work args
    }
Moises Goncalves
quelle
7
Sie müssen keinen Thread
erzeugen
4
Ich denke auch nicht, dass es eine ideale Lösung ist.
Idan Shechter
12
@IdanShechter es wäre gut, einen Grund zu nennen, warum Sie dies nicht als ideale Lösung betrachten
Omu
2
Thread kann problematisch sein, da es sich nicht um HttpRequest handelt. Einige Daten, die HttpRequest betreffen, können null sein. Zum Beispiel HttpRequest .ApplicationPath. Wenn die Aufgabe richtig geschrieben ist, funktioniert sie. Ein weiteres Problem ist der Neustart des Anwendungspools. Wenn der Pool zu oft neu gestartet wird (Speicherlecks ...), wird der Worker niemals ausgeführt.
Tomas Kubes
2
Falls mehrere Instanzen ausgeführt werden (z. B. Lastausgleich) - wahrscheinlich möchten Sie diese Lösung nicht (mehrere Aufgaben erledigen dasselbe)
Illidan
8

Verwenden Sie Windows Scheduler, um eine Webseite auszuführen.

Um zu verhindern, dass böswillige Benutzer- oder Suchmaschinenspinnen sie ausführen, rufen Sie beim Einrichten der geplanten Aufgabe einfach die Webseite mit einem Querystring auf, dh: mypage.aspx? From = Scheduledtask

Verwenden Sie dann beim Laden der Seite einfach eine Bedingung: if (Request.Querystring ["from"] == "Scheduledtask") {// executeetask}

Auf diese Weise kann kein Suchmaschinen-Spider oder böswilliger Benutzer Ihre geplante Aufgabe ausführen.

Philberg
quelle
5
Besser noch, verwenden Sie einen Salted-Hashing-Algorithmus, der den Querystring tatsächlich mit etwas mehr Sicherheit als eine magische Phrase überprüft. Die Anforderung wäre so etwas wie mypage.aspx? Salt = foo & hash = 1223523jbhdgu13t1. Sie müssen nur den gleichen Hashing-Algorithmus auf Server und Client haben. Fügen Sie außerdem eine feste Grenze für den Server hinzu. Speichern Sie, wenn es ausgeführt wurde, und verhindern Sie, dass es zu schnell ausgeführt wird. Ich könnte allerdings paranoid sein.
Nenotlep
14
Verwenden Sie Windows Scheduler noch sicherer, um eine Webseite auszuführen, die prüft, ob die Anforderung vom Server selbst stammt: Request.IsLocal>> Nur der Server selbst kann die geplanten Aufgaben ausführen, sonst niemand.
Die Verschwörung
Haben Sie mehr Erfahrungen mit Ihrem Ansatz? Ich wollte eine ähnliche Art von Service für unsere App entwickeln und kann mich jetzt nicht entscheiden, ob es besser ist, eine Seite mit geplanten Aufgaben oder Cron aufzurufen oder ob ich ein Cache-System verwenden soll.
JayDee
3

Wenn Ihre Anwendung SQL SERVER verwendet, können Sie außerdem den SQL Agent verwenden, um Ihre Aufgaben zu planen. Hier setzen wir häufig wiederkehrenden Code ein, der datengesteuert ist (E-Mail-Erinnerungen, geplante Wartung, Bereinigung usw.). Eine großartige Funktion, die in den SQL Agent integriert ist, sind Optionen zur Fehlerbenachrichtigung, mit denen Sie benachrichtigt werden können, wenn eine kritische Aufgabe fehlschlägt.

Zachary
quelle
2

Ich bin mir nicht sicher, welche Art von geplanten Aufgaben Sie meinen. Wenn Sie Aufgaben wie Aufgaben vom Typ "Jede Stunde, Aktualisierung von foo.xml" meinen, verwenden Sie das Windows-System "Geplante Aufgaben". (Der Befehl "at" oder über den Controller.) Lassen Sie ihn entweder eine Konsolen-App ausführen oder eine spezielle Seite anfordern, die den Prozess startet.

Bearbeiten: Ich sollte hinzufügen, dies ist eine gute Möglichkeit, um Ihre IIS-App auch an geplanten Punkten zum Laufen zu bringen. Angenommen, Sie möchten Ihre Datenbank alle 30 Minuten überprüfen und Benutzer per E-Mail an bestimmte Daten erinnern. Sie können geplante Aufgaben verwenden, um diese Seite anzufordern und damit IIS-Verarbeitungsaufgaben zu erhalten.

Wenn Ihre Anforderungen komplexer sind, können Sie einen Windows-Dienst erstellen und eine Schleife ausführen lassen, um die erforderliche Verarbeitung durchzuführen. Dies hat auch den Vorteil, dass der Code für Skalierungs- oder Verwaltungszwecke getrennt wird. Auf der anderen Seite müssen Sie sich mit Windows-Diensten befassen.

MichaelGG
quelle
2

Wenn Sie den Server besitzen, sollten Sie den Windows-Taskplaner verwenden. Verwenden Sie AT /? über die Befehlszeile, um die Optionen anzuzeigen.

Andernfalls müssen Sie in einer webbasierten Umgebung möglicherweise etwas Unangenehmes tun, z. B. einen anderen Computer einrichten, um in einem bestimmten Zeitintervall Anforderungen an eine bestimmte Seite zu stellen.

t3rse
quelle
2

Ich habe Abidar erfolgreich in einem ASP.NET-Projekt verwendet (hier einige Hintergrundinformationen ).

Das einzige Problem bei dieser Methode besteht darin, dass die Aufgaben nicht ausgeführt werden, wenn die ASP.NET-Webanwendung aus dem Speicher entladen wird (dh aufgrund geringer Nutzung). Ich habe versucht, alle 5 Minuten eine Aufgabe zu erstellen, um die Webanwendung aufzurufen und sie am Leben zu erhalten. Dies schien jedoch nicht zuverlässig zu funktionieren. Daher verwende ich jetzt stattdessen den Windows-Scheduler und die grundlegende Konsolenanwendung, um dies zu tun.

Die ideale Lösung ist das Erstellen eines Windows-Dienstes, obwohl dies möglicherweise nicht möglich ist (dh wenn Sie eine gemeinsam genutzte Hosting-Umgebung verwenden). Unter Wartungsgesichtspunkten ist es auch etwas einfacher, die Dinge in der Webanwendung zu halten.

Mun
quelle
1

Hier ist ein anderer Weg:

1) Erstellen Sie ein "Heartbeat" -Webskript, das für das Starten der Aufgaben verantwortlich ist, wenn diese fällig oder überfällig sind.

2) Erstellen Sie irgendwo einen geplanten Prozess (vorzugsweise auf demselben Webserver), der auf das Webskript trifft und es zwingt, es in regelmäßigen Abständen auszuführen. (z. B. Windows-Planungsaufgabe, die das Heatbeat-Skript leise mit IE oder whathaveyou startet)

Die Tatsache, dass der Aufgabencode in einem Web-Skript enthalten ist, dient lediglich dazu, den Code in der Codebasis der Webanwendung zu halten (die Annahme ist, dass beide voneinander abhängig sind), was für Webentwickler einfacher zu verwalten wäre .

Der alternative Ansatz besteht darin, ein ausführbares Serverskript / -programm zu erstellen, das den gesamten Zeitplan selbst ausführt, und die ausführbare Datei selbst als geplante Aufgabe auszuführen. Dies kann eine grundlegende Entkopplung zwischen der Webanwendung und der geplanten Aufgabe ermöglichen. Wenn Sie Ihre geplanten Aufgaben auch dann ausführen möchten, wenn die Webanwendung / Datenbank möglicherweise nicht verfügbar oder nicht erreichbar ist, sollten Sie diesen Ansatz wählen.

Matias Nino
quelle
1
@Matias, warum nicht stattdessen den geplanten Prozess die eigentliche Arbeit erledigen lassen?
LukeH
1

Mit der Methode 'ThreadPool.RegisterWaitForSingleObject' können Sie problemlos einen Windows-Dienst erstellen, der Code in Intervallen ausführt. Es ist wirklich schick und ziemlich einfach einzurichten. Diese Methode ist rationaler als die Verwendung eines der Timer im Framework.

Weitere Informationen finden Sie unter dem folgenden Link:

Ausführen eines periodischen Prozesses in .NET mithilfe eines Windows-Dienstes:
http://allen-conway-dotnet.blogspot.com/2009/12/running-periodic-process-in-net-using.html

atconway
quelle
0

Wir verwenden auch Konsolenanwendungen. Wenn Sie Protokollierungstools wie Log4net verwenden, können Sie deren Ausführung ordnungsgemäß überwachen. Ich bin mir auch nicht sicher, wie sie schwieriger zu warten sind als eine Webseite, da Sie möglicherweise einige der gleichen Codebibliotheken zwischen den beiden gemeinsam nutzen, wenn sie ordnungsgemäß entworfen wurden.

Wenn Sie dagegen sind, dass diese Aufgaben zeitgesteuert ausgeführt werden, befindet sich möglicherweise eine Webseite in Ihrem Verwaltungsbereich Ihrer Website, die als Warteschlange fungiert. Der Benutzer gibt eine Anforderung zum Ausführen der Aufgabe ein. Anschließend wird ein leerer Datenstempeldatensatz in die MyProcessQueue-Tabelle eingefügt, und Ihre geplante Aufgabe sucht alle X Minuten nach einem neuen Datensatz in MyProcessQueue. Auf diese Weise wird es nur ausgeführt, wenn der Kunde dies wünscht.

Hoffe, diese Vorschläge helfen.

Kyle B.
quelle
0

Eine Möglichkeit wäre, einen Windows-Dienst einzurichten und diesen zum Aufrufen Ihrer geplanten Aufgabe zu veranlassen.

In Winforms, die ich mit Timern verwendet habe, glaube ich nicht, dass dies in ASP.NET gut funktionieren würde

AJM
quelle
-1

Eine neue Task Scheduler-Klassenbibliothek für .NET

Hinweis: Seit diese Bibliothek erstellt wurde, hat Microsoft einen neuen Taskplaner (Task Scheduler 2.0) für Windows Vista eingeführt. Diese Bibliothek ist ein Wrapper für die Task Scheduler 1.0-Oberfläche, die in Vista weiterhin verfügbar ist und mit Windows XP, Windows Server 2003 und Windows 2000 kompatibel ist.

http://www.codeproject.com/KB/cs/tsnewlib.aspx

Ali
quelle
Bitte löschen. Es wurde unten beantwortet. Duplizieren
Fandango68