Najlepszy sposób na uruchomienie zaplanowanych zadań [zamknięte]

229

Dzisiaj zbudowaliśmy aplikację konsolową do uruchamiania zaplanowanych zadań dla naszej strony internetowej ASP.NET. Myślę jednak, że takie podejście jest nieco podatne na błędy i trudne do utrzymania. Jak wykonać zaplanowane zadanie (w środowisku Windows / IIS / ASP.NET)

Aktualizacja:

Przykłady zadań:

  • Wysyłanie wiadomości e-mail z kolejki wiadomości e-mail w bazie danych
  • Usuwanie nieaktualnych obiektów z bazy danych
  • Pobieranie statystyk z Google AdWords i wypełnianie tabeli w bazie danych.
Niels Bosma
źródło
Jaki jest przykład wykonywanych zadań?
JeffO
4
Musisz sprawdzić atrigger.com
Kousha
Jeśli masz Plesk, możesz napisać vbs i reklamować go w Harmonogramie zadań: net24.co.nz/kb/article/AA-00213/13/Shared-Hosting/ASP-ASP.NET/…
HasanG

Odpowiedzi:

74

Wszystkie moje zadania (które należy zaplanować) dla strony internetowej są przechowywane na stronie internetowej i wywoływane ze specjalnej strony. Potem napisałem prostą usługę Windows, która tak często nazywa tę stronę. Po uruchomieniu strony zwraca wartość. Jeśli wiem, że jest więcej do zrobienia, od razu uruchamiam stronę, w przeciwnym razie uruchamiam ją za chwilę. Działa to dla mnie naprawdę dobrze i zachowuje całą logikę moich zadań w kodzie internetowym. Przed napisaniem prostej usługi Windows korzystałem z harmonogramu Windows, aby wywoływać stronę co x minut.

Innym wygodnym sposobem na uruchomienie tego jest skorzystanie z usługi monitorowania, takiej jak Pingdom . Skieruj ich sprawdzenie http na stronę, na której działa Twój kod usługi. Niech strona zwraca wyniki, które następnie mogą zostać użyte do uruchomienia Pingdom w celu wysyłania komunikatów ostrzegawczych, gdy coś jest nie tak.

Brettski
źródło
3
To jest rozwiązanie, z którym skończyłem. Zamiast niestandardowej usługi sieciowej używam Windows Schedulera + curl. Jaka jest korzyść z korzystania z usługi Windows.
Niels Bosma
16
Czy spojrzałeś na technikę wygasania przedmiotu z pamięci podręcznej? Myślę, że przekonasz się, że jest to znacznie bardziej idealna implementacja zaplanowanej usługi: codeproject.com/KB/aspnet/ASPNETService.aspx
Richard Clayton
10
Co powstrzyma złośliwego użytkownika (lub pająka wyszukiwarki) przed wywołaniem tej strony, a tym samym spowoduje uruchomienie zaplanowanych zadań?
UpTheCreek
8
Możesz zatrzymać szkodliwe połączenia, przechowując statyczny znacznik czasu w aplikacji internetowej i działając tylko wtedy, gdy nie został ustawiony znacznik czasu (pierwsze połączenie) lub upłynął właściwy czas od ostatniego połączenia.
Rob Kent
5
Zatrzymuję złośliwe połączenia z moim adresem URL, sprawdzając, czy adres IP jest adresem wewnętrznym, czy nie. Nic nie zwraca i nic nie robi, jeśli nie jest to wewnętrzne dla naszej organizacji.
user1408767,
128

Ta technika autorstwa Jeffa Atwooda dla Stackoverflow jest najprostszą metodą, na jaką się natknąłem. Opiera się on na mechanizmie zwrotnym „usunięto element pamięci podręcznej” wbudowanym w system pamięci podręcznej programu ASP.NET

Aktualizacja: Stackoverflow przerósł tę metodę. Działa tylko podczas działania strony, ale jest to bardzo prosta technika, która jest przydatna dla wielu osób.

Sprawdź także Quartz.NET

PNE.
źródło
12
Co się dzieje, jeśli aplikacja nie działa, ale zaplanowane zadanie musi się zdarzyć?
MichaelGG
2
Może to również spowolnić działanie użytkownika, jeśli zadanie zajmie trochę czasu, aby uruchomić ten czas. Wolę, aby użytkownik nie spawnował dla mnie mojej konserwacji / zadań.
Brettski
5
To jest straszne jak diabli! Wszystko może spowodować, że aplikacja przestanie działać i prawdopodobnie uruchomi się ponownie tylko przy następnym żądaniu użytkownika. Pomiędzy tymi czasami twoje zadania się nie uruchamiają!
teedyay
43
Coś zauważyłem dzisiaj w komentarzach do oryginalnego postu na blogu: 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 Z tym podejściem jest duża wada. Za każdym razem, gdy aplikacja zostanie ponownie przetworzona, zostanie uruchomione zdarzenie „CacheItemRemoved” i uruchomione zostanie zaplanowane zadanie. W zakładach produkcyjnych może się to zdarzać kilka razy dziennie. Nie tak dobrze, jeśli chcesz, aby zadanie było uruchamiane co tydzień.
Steven de Salas,
30

Utwórz niestandardową usługę systemu Windows .

Miałem kilka krytycznych zadań skonfigurowanych jako zaplanowane aplikacje konsolowe i miałem trudności z utrzymaniem. Utworzyłem usługę systemu Windows z „pulsem”, która sprawdzałaby harmonogram w mojej bazie danych co kilka minut. Wyszło naprawdę dobrze.

Mimo to nadal używam zaplanowanych aplikacji konsolowych do większości niekrytycznych zadań konserwacyjnych. Jeśli nie jest zepsuty, nie naprawiaj go.

Chris Van Opstal
źródło
7
Do Twojej wiadomości link już nie działa.
Charles Burns
1
@CharlesBurns, zawsze możesz przeglądać martwe linki za pomocą archive.org: web.archive.org/web/20090919131944/http://www.dotheweb.net/…
Nikolay Kostov
17

Dla wszystkich zaangażowanych było to łatwe:

  • Utwórz metodę usługi internetowej, taką jak DoSuchAndSuchProcess
  • Utwórz aplikację konsoli, która wywołuje tę metodę internetową.
  • Zaplanuj aplikację konsoli w harmonogramie zadań.

Korzystając z tej metodologii, cała logika biznesowa jest zawarta w Twojej aplikacji internetowej, ale masz pewność, że menedżer zadań systemu Windows lub dowolny inny menedżer zadań komercyjnych uruchomi go i zarejestruje wszelkie informacje zwrotne, takie jak raport z wykonania. Korzystanie z usługi internetowej zamiast publikowania na stronie ma pewną zaletę, ponieważ łatwiej jest uzyskać dane zwrotne z usługi internetowej.

Daniel Auger
źródło
10

Po co wymyślać koło ponownie, użyj klasy Gwintowanie i Timer.

    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
źródło
7
Nie musisz
odradzać
4
Ja też nie uważam, że jest to idealne rozwiązanie.
Idan Shechter
12
@IdanShechter dobrze byłoby powiedzieć powód dlaczego rozważyć to nie idealne rozwiązanie
Omu
2
Wątek może być problematyczny, ponieważ nie jest to HttpRequest, niektóre dane dotyczące HttpRequest mogą być puste. Na przykład HttpRequest .ApplicationPath. Jeśli zadanie zostanie napisane poprawnie, zadziała. Innym problemem jest ponowne uruchomienie puli aplikacji. Jeśli pula zbyt często się restartuje (wycieki pamięci ...), proces roboczy nigdy się nie uruchomi.
Tomas Kubes
2
Jeśli masz kilka uruchomionych instancji (np. Równoważenie obciążenia) - prawdopodobnie nie chciałbyś tego rozwiązania (kilka zadań robi to samo)
Illidan
8

Użyj Windows Scheduler, aby uruchomić stronę internetową.

Aby zapobiec złośliwemu działaniu pająka użytkownika lub wyszukiwarki, aby go uruchomić, po skonfigurowaniu zaplanowanego zadania wystarczy wywołać stronę internetową za pomocą kwerendy, tj .: mypage.aspx? From = scheduletask

Następnie podczas ładowania strony użyj warunku: if (Request.Querystring ["from"] == "scheduletask") {// executetask}

W ten sposób żaden pająk wyszukiwarki lub złośliwy użytkownik nie będzie w stanie wykonać zaplanowanego zadania.

philberg
źródło
5
Jeszcze lepiej, użyj algorytmu mieszania solonego, który faktycznie weryfikuje kwerendę z nieco większym bezpieczeństwem niż magiczną frazą. Wymagane byłoby coś takiego jak mypage.aspx? Salt = foo & hash = 1223523jbhdgu13t1. Musisz tylko mieć ten sam algorytm mieszający na serwerze i kliencie. Dodaj także twardy limit na serwerze; zapisz, kiedy został wykonany i zapobiegaj zbyt szybkiemu wykonywaniu. Mogę być paranoikiem.
Nenotlep
14
Jeszcze bardziej bezpieczne, użyj Windows Scheduler, aby uruchomić stronę internetową, która sprawdza, czy żądanie pochodzi z samego serwera: Request.IsLocal>> tylko sam serwer może uruchamiać zaplanowane zadania, nikt inny.
Spisek
Czy masz więcej doświadczeń ze swojego podejścia? Zamierzałem opracować podobny rodzaj usługi dla naszej aplikacji i teraz nie mogę zdecydować, czy lepiej wywołać stronę z zaplanowanym zadaniem lub cronem, czy też użyć systemu pamięci podręcznej.
JayDee
3

Dodatkowo, jeśli twoja aplikacja korzysta z SQL SERVER, możesz użyć SQL Agent do zaplanowania swoich zadań. W tym miejscu zwykle umieszczamy powtarzający się kod oparty na danych (przypomnienia e-mail, zaplanowana konserwacja, czyszczenie itp.). Świetną funkcją wbudowaną w SQL Agenta są opcje powiadamiania o awariach, które mogą ostrzegać w przypadku niepowodzenia zadania krytycznego.

Zachary
źródło
2

Nie jestem pewien, jakie masz na myśli zaplanowane zadania. Jeśli masz na myśli zadania typu „co godzinę, odśwież plik foo.xml”, skorzystaj z systemu Windows Zaplanowane zadania. (Polecenie „at” lub za pośrednictwem kontrolera). Niech uruchomi aplikację konsolową lub poprosi o specjalną stronę rozpoczynającą proces.

Edycja: powinienem dodać, to jest OK sposób na uruchomienie aplikacji IIS również w zaplanowanych punktach. Załóżmy więc, że chcesz sprawdzać swoją bazę danych co 30 minut i wysyłać użytkownikom przypomnienia e-mailem o niektórych danych, możesz użyć zaplanowanych zadań, aby poprosić o tę stronę, a tym samym uzyskać IIS.

Jeśli Twoje potrzeby są bardziej złożone, możesz rozważyć utworzenie usługi systemu Windows i uruchomienie jej w pętli w celu wykonania dowolnego potrzebnego przetwarzania. Ma to również tę zaletę, że wyodrębnia kod do celów skalowania lub zarządzania. Z drugiej strony musisz poradzić sobie z usługami Windows.

MichaelGG
źródło
2

Jeśli jesteś właścicielem serwera, powinieneś użyć harmonogramu zadań Windows. Użyj AT /? z wiersza poleceń, aby wyświetlić opcje.

W przeciwnym razie ze środowiska internetowego może być konieczne wykonanie czegoś nieprzyjemnego, na przykład skonfigurowanie innego komputera w celu wysyłania żądań do określonej strony w określonych odstępach czasu.

t3rse
źródło
2

Z powodzeniem korzystałem z Abidara w projekcie ASP.NET (oto kilka podstawowych informacji ).

Jedynym problemem związanym z tą metodą jest to, że zadania nie zostaną uruchomione, jeśli aplikacja sieci Web ASP.NET zostanie zwolniona z pamięci (tj. Z powodu niskiego zużycia). Jedną rzeczą, którą próbowałem, jest tworzenie zadania, aby uderzać w aplikację internetową co 5 minut, utrzymując ją przy życiu, ale nie wydawało się to działać niezawodnie, więc teraz używam do tego harmonogramu Windows i podstawowej aplikacji konsoli.

Idealnym rozwiązaniem jest utworzenie usługi systemu Windows, choć może to nie być możliwe (np. Jeśli korzystasz ze współdzielonego środowiska hostingowego). Ułatwia to także utrzymanie aplikacji w sieci z punktu widzenia konserwacji.

Mun
źródło
1

Oto inny sposób:

1) Utwórz skrypt internetowy „bicie serca”, który będzie odpowiedzialny za uruchamianie zadań, jeśli są one należne lub zaległe do uruchomienia.

2) Utwórz gdzieś zaplanowany proces (najlepiej na tym samym serwerze), który uderzy w skrypt i zmusi go do działania w regularnych odstępach czasu. (np. zadanie harmonogramu systemu Windows, które po cichu uruchamia skrypt Heatbeat za pomocą IE lub co chcesz)

Fakt, że kod zadania jest zawarty w skrypcie internetowym, służy wyłącznie utrzymaniu kodu w bazie kodu aplikacji internetowej (założono, że oba są od siebie zależne), co byłoby łatwiejsze dla programistów stron internetowych do zarządzania .

Alternatywnym podejściem jest utworzenie skryptu / programu serwera wykonawczego, który sam wykonuje cały harmonogram i uruchamia sam plik wykonywalny jako zaplanowane zadanie. Może to pozwolić na zasadnicze oddzielenie aplikacji sieciowej od zaplanowanego zadania. Dlatego jeśli chcesz, aby zaplanowane zadania działały nawet wtedy, gdy aplikacja / baza danych mogła być niedostępna lub niedostępna, powinieneś zastosować to podejście.

Matias Nino
źródło
1
@Matias, dlaczego zamiast tego zaplanowany proces wykona prawdziwą pracę?
Łukasza
1

Za pomocą metody „ThreadPool.RegisterWaitForSingleObject” można łatwo utworzyć usługę Windows, która uruchamia kod w odstępach czasu. Konfiguracja jest bardzo prosta i łatwa. Ta metoda jest bardziej uproszczona niż użycie dowolnego z timerów w ramach.

Aby uzyskać więcej informacji, zobacz poniższy link:

Uruchamianie procesu okresowego w .NET przy użyciu usługi Windows:
http://allen-conway-dotnet.blogspot.com/2009/12/running-periodic-process-in-net-using.html

atconway
źródło
0

Korzystamy również z aplikacji konsolowych. Jeśli korzystasz z narzędzi do rejestrowania, takich jak Log4net, możesz odpowiednio monitorować ich wykonanie. Nie jestem też pewien, w jaki sposób są trudniejsze w utrzymaniu niż strona internetowa, biorąc pod uwagę, że możesz udostępniać niektóre z tych samych bibliotek kodów między tymi dwoma, jeśli są one odpowiednio zaprojektowane.

Jeśli sprzeciwisz się uruchamianiu tych zadań na czas, w sekcji administracyjnej witryny internetowej może znajdować się strona internetowa, która działa jak kolejka. Użytkownik wysyła żądanie uruchomienia zadania, z kolei wstawia pusty rekord datestampu w tabeli MyProcessQueue, a zaplanowane zadanie sprawdza co X minut nowy rekord w MyProcessQueue. W ten sposób działa tylko wtedy, gdy klient chce, aby to działało.

Mam nadzieję, że te sugestie pomogą.

Kyle B.
źródło
0

Jedną z opcji byłoby skonfigurowanie usługi systemu Windows i wywołanie zaplanowanego zadania.

W winformach, w których używałem Timerów, nie sądzę, że to zadziała dobrze w ASP.NET

AJM
źródło
-1

Nowa biblioteka klas harmonogramu zadań dla platformy .NET

Uwaga: Od czasu utworzenia tej biblioteki Microsoft wprowadził nowy harmonogram zadań (Task Scheduler 2.0) dla systemu Windows Vista. Ta biblioteka jest opakowaniem dla interfejsu Task Scheduler 1.0, który jest nadal dostępny w systemie Vista i jest kompatybilny z Windows XP, Windows Server 2003 i Windows 2000.

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

Ali
źródło
Proszę usunąć. Odpowiedź została udzielona poniżej. Duplikat
Fandango68,