Il modo migliore per eseguire le attività pianificate [chiuso]


229

Oggi abbiamo creato un'applicazione console per l'esecuzione delle attività pianificate per il nostro sito Web ASP.NET. Ma penso che questo approccio sia un po 'soggetto a errori e difficile da mantenere. Come si esegue l'attività pianificata (in un ambiente Windows / IIS / ASP.NET)

Aggiornare:

Esempi di compiti:

  • Invio di e-mail da una coda e-mail nel database
  • Rimozione di oggetti obsoleti dal database
  • Recupero delle statistiche da Google AdWords e compilazione di una tabella nel database.

Qual è un esempio delle attività che stai eseguendo?
JeffO,

4
Devi controllare atrigger.com
Kousha il

Se hai Plesk puoi scrivere un vbs e pubblicarlo nell'Utilità di
HasanG il

Risposte:


74

Tutte le mie attività (che devono essere programmate) per un sito Web sono conservate all'interno del sito Web e richiamate da una pagina speciale. Ho quindi scritto un semplice servizio di Windows che chiama questa pagina ogni tanto. Una volta eseguita la pagina restituisce un valore. Se so che c'è ancora molto lavoro da fare, eseguo di nuovo la pagina immediatamente, altrimenti la eseguo tra poco. Questo ha funzionato davvero bene per me e mantiene tutta la mia logica di attività con il codice web. Prima di scrivere il semplice servizio di Windows, ho usato l'utilità di pianificazione di Windows per chiamare la pagina ogni x minuti.

Un altro modo conveniente per eseguire questo è utilizzare un servizio di monitoraggio come Pingdom . Puntare il loro controllo http sulla pagina che esegue il codice di servizio. Avere i risultati di ritorno della pagina che possono quindi essere utilizzati per attivare Pingdom per inviare messaggi di avviso quando qualcosa non va.


3
Questa è la soluzione con cui sono finito. Invece di un servizio Web personalizzato, utilizzo Windows Scheduler + Curl. Qual è il vantaggio di utilizzare un servizio Windows.
Niels Bosma,

16
Hai esaminato la tecnica di scadenza degli oggetti cache? Penso che scoprirai che si tratta di un'implementazione molto più ideale di un servizio pianificato: codeproject.com/KB/aspnet/ASPNETService.aspx
Richard Clayton,

10
Cosa impedisce a un utente malintenzionato (o a uno spider dei motori di ricerca) di chiamare questa pagina, causando così l'esecuzione delle attività pianificate?
UpTheCreek,

8
È possibile interrompere le chiamate dannose memorizzando un timestamp statico nell'app Web ed eseguendolo solo se il timestamp non è stato impostato (prima chiamata) o il tempo corretto è scaduto dall'ultima chiamata.
Rob Kent,

5
Fermo le chiamate dannose al mio URL controllando se l'indirizzo IP è un indirizzo interno o meno. Non restituisce nulla e non fa nulla se non è interno alla nostra organizzazione.
user1408767

128

Questa tecnica di Jeff Atwood per Stackoverflow è il metodo più semplice che abbia mai incontrato. Si basa sul meccanismo di callback "elemento cache rimosso" incorporato nel sistema cache di ASP.NET

Aggiornamento: Stackoverflow ha superato questo metodo. Funziona solo mentre il sito Web è in esecuzione ma è una tecnica molto semplice che è utile per molte persone.

Dai un'occhiata anche a Quartz.NET


12
Quindi cosa succede se l'applicazione non è in esecuzione, ma deve essere eseguita l'attività pianificata?
MichaelGG,

2
Ciò potrebbe anche rallentare l'esperienza dell'utente se l'attività dovesse richiedere del tempo per essere eseguita questa volta. Preferisco che l'utente non generi la mia manutenzione / attività per me.
Brettski,

5
Questo è spaventoso da morire! Qualsiasi cosa potrebbe causare il blocco dell'applicazione e probabilmente si riavvierebbe solo alla successiva richiesta dell'utente. Tra quei tempi, i tuoi compiti non vengono eseguiti!
martedì

43
Qualcosa che ho notato oggi nei commenti al post originale del blog: 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 C'è un grosso difetto con questo approccio. Ogni volta che l'applicazione viene riciclata, l'evento 'CacheItemRemoved' viene generato e l'attività pianificata verrà eseguita. Nei siti di produzione ciò può accadere alcune volte al giorno. Non così buono se si desidera che l'attività venga eseguita settimanalmente.
Steven de Salas,

30

Crea un servizio Windows personalizzato .

Avevo alcune attività mission-critical configurate come app di console pianificate e le trovavo difficili da mantenere. Ho creato un servizio Windows con un "battito cardiaco" che controllava un programma nel mio DB ogni paio di minuti. Ha funzionato davvero bene.

Detto questo, continuo a utilizzare app di console pianificate per la maggior parte delle mie attività di manutenzione non critica. Se non è rotto, non aggiustarlo.


7
Cordiali saluti il ​​link è ora morto.
Charles Burns,

1
@CharlesBurns, puoi sempre consultare i link non funzionanti con archive.org: web.archive.org/web/20090919131944/http://www.dotheweb.net/…
Nikolay Kostov

17

Ho trovato che questo è facile per tutti i soggetti coinvolti:

  • Creare un metodo di servizio web come DoSuchAndSuchProcess
  • Crea un'app console che chiama questo metodo web.
  • Pianifica l'app console nell'utilità di pianificazione.

Utilizzando questa metodologia tutta la logica aziendale è contenuta nella tua app Web, ma hai l'affidabilità del Task Manager di Windows o di qualsiasi altro Task Manager commerciale per dare il via e registrare tutte le informazioni di restituzione come un rapporto di esecuzione. L'utilizzo di un servizio Web anziché la pubblicazione su una pagina presenta alcuni vantaggi, poiché è più semplice ottenere dati di restituzione da un servizio Web.


10

Perché reinventare la ruota, utilizzare la classe Threading e 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
    }

7
Non è necessario generare un thread per avviare un timer ...
Zyo

4
Anch'io non penso che sia una soluzione ideale.
Idan Shechter,

12
@IdanShechter sarebbe bene dire una ragione per cui non la consideri una soluzione ideale
Omu,

2
Il thread potrebbe essere problematico, poiché non è HttpRequest, alcuni dati che coinvolgono HttpRequest possono essere nulli. Ad esempio HttpRequest .ApplicationPath. Se l'attività è scritta correttamente, funzionerà. Un altro problema è il riavvio del pool di applicazioni. Se il pool si riavvia troppo spesso (perdite di memoria ...), il lavoratore non verrà mai eseguito.
Tomas Kubes,

2
Nel caso in cui siano in esecuzione più istanze (ad es. Bilanciamento del carico), probabilmente non si vorrebbe questa soluzione (diverse attività fanno lo stesso)
Illidan

8

Utilizzare l'Utilità di pianificazione di Windows per eseguire una pagina Web.

Per evitare che utenti maliziosi o spider dei motori di ricerca possano eseguirlo, quando si imposta l'attività pianificata, è sufficiente chiamare la pagina Web con una stringa di query, ad esempio: mypage.aspx? From = scheduletask

Quindi nel caricamento della pagina, utilizza semplicemente una condizione: if (Request.Querystring ["from"] == "scheduletask") {//ecutetask}

In questo modo nessuno spider dei motori di ricerca o utenti malintenzionati saranno in grado di eseguire l'attività pianificata.


5
Meglio ancora, usa un algoritmo di hash salato che verifica effettivamente la querystring con un po 'più di sicurezza di una frase magica. Il req sarebbe qualcosa come mypage.aspx? Salt = foo & hash = 1223523jbhdgu13t1. Devi solo avere lo stesso algoritmo di hashing sia sul server che sul client. Aggiungere anche un limite rigido sul server; salva quando è stato eseguito e impedisce l'esecuzione troppo veloce. Potrei essere paranoico però.
Nenotlep

14
Ancora più sicuro, usa l'Utilità di pianificazione di Windows per eseguire una pagina Web che controlla se la richiesta proviene dal server stesso: Request.IsLocal>> solo il server stesso può eseguire le attività pianificate, nessun altro.
The Conspiracy,

Hai più esperienze dal tuo approccio? Stavo per sviluppare un tipo simile di servizio della nostra app e ora non riesco a decidere se è meglio chiamare una pagina con attività pianificata o cron o se utilizzare il sistema cache.
JayDee,


3

Inoltre, se l'applicazione utilizza SQL SERVER è possibile utilizzare SQL Agent per pianificare le attività. Qui è dove comunemente mettiamo il codice ricorrente che è guidato dai dati (promemoria via e-mail, manutenzione programmata, eliminazioni, ecc ...). Una grande funzionalità integrata con SQL Agent sono le opzioni di notifica degli errori, che possono avvisare se un'attività critica non riesce.


2

Non sono sicuro del tipo di attività pianificate che intendi. Se intendi cose come "ogni ora, aggiorna foo.xml", digita le attività, quindi usa il sistema delle Attività pianificate di Windows. (Il comando "at" o tramite il controller.) Avere o eseguire un'app console o richiedere una pagina speciale che avvia il processo.

Modifica: dovrei aggiungere, questo è un modo OK per far funzionare la tua app IIS anche nei punti programmati. Supponiamo quindi che tu voglia controllare il tuo DB ogni 30 minuti e inviare e-mail di promemoria agli utenti su alcuni dati, puoi usare le attività pianificate per richiedere questa pagina e quindi ottenere che IIS elabori le cose.

Se le tue esigenze sono più complesse, potresti prendere in considerazione la creazione di un servizio Windows e l'esecuzione di un ciclo per eseguire qualsiasi elaborazione di cui hai bisogno. Ciò ha anche il vantaggio di separare il codice a fini di ridimensionamento o gestione. L'aspetto negativo è che devi occuparti dei servizi di Windows.


2

Se sei il proprietario del server, devi utilizzare l'utilità di pianificazione di Windows. Usa AT /? dalla riga di comando per visualizzare le opzioni.

Altrimenti, da un ambiente basato sul web, potresti dover fare qualcosa di brutto come impostare una macchina diversa per effettuare richieste a una determinata pagina in un intervallo di tempo.


2

Ho usato Abidar con successo in un progetto ASP.NET (ecco alcune informazioni di base ).

L'unico problema con questo metodo è che le attività non verranno eseguite se l'applicazione Web ASP.NET viene scaricata dalla memoria (ad es. A causa del basso utilizzo). Una cosa che ho provato è creare un'attività per colpire l'applicazione Web ogni 5 minuti, mantenendola in vita, ma questo non sembra funzionare in modo affidabile, quindi ora sto usando lo scheduler di Windows e l'applicazione console di base per farlo.

La soluzione ideale è la creazione di un servizio Windows, sebbene ciò potrebbe non essere possibile (ad es. Se si utilizza un ambiente di hosting condiviso). Rende anche le cose un po 'più facili dal punto di vista della manutenzione per mantenere le cose all'interno dell'applicazione web.


1

Ecco un altro modo:

1) Creare uno script Web "heartbeat" responsabile dell'avvio delle attività se sono scadute o scadute.

2) Creare un processo pianificato da qualche parte (preferibilmente sullo stesso server Web) che colpisce lo script Web e lo costringe a funzionare a intervalli regolari. (ad es. attività di pianificazione di Windows che avvia silenziosamente lo script Heatbeat utilizzando IE o whathaveyou)

Il fatto che il codice attività sia contenuto in uno script Web ha il solo scopo di mantenere il codice all'interno della base di codice dell'applicazione Web (il presupposto è che entrambi dipendono l'uno dall'altro), che sarebbe più facile da gestire per gli sviluppatori Web .

L'approccio alternativo consiste nel creare uno script / programma del server eseguibile che esegua tutta la pianificazione stessa ed esegua l'eseguibile stesso come attività pianificata. Ciò può consentire il disaccoppiamento fondamentale tra l'applicazione Web e l'attività pianificata. Pertanto, se è necessario eseguire le attività pianificate anche nel caso in cui l'app / il database Web siano inattivi o inaccessibili, è necessario seguire questo approccio.


1
@Matias, Perché non solo il processo pianificato fa il vero lavoro invece?
Luca,

1

È possibile creare facilmente un servizio Windows che esegue il codice a intervalli utilizzando il metodo "ThreadPool.RegisterWaitForSingleObject". È davvero semplice e abbastanza facile da configurare. Questo metodo è un approccio più semplificato rispetto all'utilizzo di uno qualsiasi dei timer nel Framework.

Dai un'occhiata al link qui sotto per maggiori informazioni:

Esecuzione di un processo periodico in .NET utilizzando un servizio di Windows:
http://allen-conway-dotnet.blogspot.com/2009/12/running-periodic-process-in-net-using.html


0

Utilizziamo anche applicazioni console. Se si utilizzano strumenti di registrazione come Log4net, è possibile monitorare correttamente la loro esecuzione. Inoltre, non sono sicuro di come siano più difficili da gestire rispetto a una pagina Web, dato che potresti condividere alcune delle stesse librerie di codici tra i due se è progettato correttamente.

Se sei contrario a eseguire tali attività a tempo, potresti avere una pagina web nella sezione amministrativa del tuo sito Web che funge da coda. L'utente inserisce una richiesta per eseguire l'attività, a sua volta inserisce un record di datastamp vuoto nella tabella MyProcessQueue e l'attività pianificata controlla ogni X minuti un nuovo record in MyProcessQueue. In questo modo, funziona solo quando il cliente vuole che funzioni.

Spero che questi suggerimenti siano d'aiuto.


0

Un'opzione sarebbe quella di impostare un servizio Windows e farlo chiamare per l'attività pianificata.

Nei winform che ho usato, i timer messi non pensano che funzionerebbe bene in ASP.NET


-1

Una nuova libreria di classi dell'utilità di pianificazione per .NET

Nota: da quando è stata creata questa libreria, Microsoft ha introdotto un nuovo scheduler (Task Scheduler 2.0) per Windows Vista. Questa libreria è un wrapper per l'interfaccia Task Scheduler 1.0, che è ancora disponibile in Vista ed è compatibile con Windows XP, Windows Server 2003 e Windows 2000.

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


Per piacere cancella. Di seguito è stata data una risposta. Duplicato
Fandango68
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.