Meilleur moyen d'exécuter des tâches planifiées [fermé]

229

Aujourd'hui, nous avons créé une application console pour exécuter les tâches planifiées de notre site Web ASP.NET. Mais je pense que cette approche est un peu sujette aux erreurs et difficile à maintenir. Comment exécutez-vous votre tâche planifiée (dans un environnement Windows / IIS / ASP.NET)

Mettre à jour:

Exemples de tâches:

  • Envoi de courriels à partir d'une file d'attente de courriels dans la base de données
  • Suppression d'objets obsolètes de la base de données
  • Récupérer les statistiques de Google AdWords et remplir un tableau dans la base de données.
Niels Bosma
la source
Quel est un exemple des tâches que vous exécutez?
JeffO
4
Vous devez vérifier atrigger.com
Kousha
Si vous avez Plesk, vous pouvez écrire un vbs et le publier dans le Planificateur de tâches: net24.co.nz/kb/article/AA-00213/13/Shared-Hosting/ASP-ASP.NET/…
HasanG

Réponses:

74

Toutes mes tâches (qui doivent être planifiées) pour un site Web sont conservées dans le site Web et appelées à partir d'une page spéciale. J'ai ensuite écrit un service Windows simple qui appelle cette page de temps en temps. Une fois la page lancée, elle renvoie une valeur. Si je sais qu'il y a encore du travail à faire, je lance à nouveau la page tout de suite, sinon je l'exécute dans un petit moment. Cela a très bien fonctionné pour moi et conserve toute ma logique de tâche avec le code Web. Avant d'écrire le service Windows simple, j'ai utilisé le planificateur Windows pour appeler la page toutes les x minutes.

Un autre moyen pratique d'exécuter cela consiste à utiliser un service de surveillance comme Pingdom . Pointez leur vérification http vers la page qui exécute votre code de service. Demandez à la page de renvoyer des résultats qui peuvent ensuite être utilisés pour déclencher Pingdom pour envoyer des messages d'alerte lorsque quelque chose ne va pas.

Brettski
la source
3
C'est la solution avec laquelle je me suis retrouvé. Au lieu d'un service Web personnalisé, j'utilise le planificateur de fenêtres + curl. Quel est l'avantage d'utiliser un service Windows.
Niels Bosma
16
Avez-vous étudié la technique d'expiration de l'élément de cache? Je pense que vous constaterez qu'il s'agit d'une implémentation beaucoup plus idéale d'un service planifié: codeproject.com/KB/aspnet/ASPNETService.aspx
Richard Clayton
10
Qu'est-ce qui empêche un utilisateur malveillant (ou une araignée de moteur de recherche) d'appeler cette page et de provoquer ainsi l'exécution de vos tâches planifiées?
UpTheCreek
8
Vous pouvez arrêter les appels malveillants en stockant un horodatage statique dans l'application Web et en ne l'exécutant que si l'horodatage n'a pas été défini (premier appel) ou si l'heure correcte a expiré depuis le dernier appel.
Rob Kent
5
J'arrête les appels malveillants à mon URL en vérifiant si l'adresse IP est une adresse interne ou non. Il ne renvoie rien et ne fait rien s'il n'est pas interne à notre organisation.
user1408767
128

Cette technique de Jeff Atwood pour Stackoverflow est la méthode la plus simple que j'ai rencontrée. Il repose sur le mécanisme de rappel «Élément de cache supprimé» intégré au système de cache d'ASP.NET

Mise à jour: Stackoverflow a dépassé cette méthode. Cela ne fonctionne que lorsque le site Web fonctionne, mais c'est une technique très simple qui est utile pour de nombreuses personnes.

Consultez également Quartz.NET

AVANT JC.
la source
12
Que se passe-t-il si l'application n'est pas en cours d'exécution, mais que la tâche planifiée doit se produire?
MichaelGG
2
Cela pourrait également ralentir l'expérience utilisateur si la tâche prenait du temps à s'exécuter cette fois. Je préfère que l'utilisateur ne génère pas ma maintenance / mes tâches pour moi.
Brettski
5
C'est effrayant comme l'enfer! Tout pourrait entraîner l'arrêt de l'exécution de l'application et elle ne redémarrerait probablement qu'à la demande de l'utilisateur suivant. Entre ces moments, vos tâches ne s'exécutent pas!
teedyay
43
Quelque chose que j'ai remarqué aujourd'hui dans les commentaires du blog original: 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 Theres un gros défaut avec cette approche. Chaque fois que l'application est recyclée, l'événement «CacheItemRemoved» se déclenche et votre tâche planifiée s'exécute. Sur les sites de production, cela peut se produire plusieurs fois par jour. Pas si bon si vous voulez que la tâche s'exécute chaque semaine.
Steven de Salas
30

Créez un service Windows personnalisé .

J'ai eu des tâches stratégiques définies en tant qu'applications de console planifiées et je les ai trouvées difficiles à maintenir. J'ai créé un service Windows avec un «battement de cœur» qui vérifierait un calendrier dans ma base de données toutes les deux minutes. Cela a très bien fonctionné.

Cela dit, j'utilise toujours des applications de console planifiées pour la plupart de mes tâches de maintenance non critiques. Si ce n'est pas cassé, ne le réparez pas.

Chris Van Opstal
la source
7
Pour info le lien est maintenant mort.
Charles Burns
1
@CharlesBurns, vous pouvez toujours parcourir les liens morts avec archive.org: web.archive.org/web/20090919131944/http://www.dotheweb.net/…
Nikolay Kostov
17

J'ai trouvé que c'était facile pour toutes les personnes impliquées:

  • Créez une méthode de service Web telle que DoSuchAndSuchProcess
  • Créez une application console qui appelle cette méthode Web.
  • Planifiez l'application console dans le planificateur de tâches.

En utilisant cette méthodologie, toute la logique métier est contenue dans votre application Web, mais vous avez la fiabilité du gestionnaire de tâches Windows ou de tout autre gestionnaire de tâches commerciales pour le lancer et enregistrer toutes les informations de retour telles qu'un rapport d'exécution. L'utilisation d'un service Web au lieu de publier sur une page présente un certain avantage, car il est plus facile d'obtenir des données de retour d'un service Web.

Daniel Auger
la source
10

Pourquoi réinventer la roue, utilisez la classe Threading et 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
la source
7
Vous n'avez pas besoin de générer un thread pour démarrer une minuterie ...
Zyo
4
Moi aussi, je ne pense pas que ce soit une solution idéale.
Idan Shechter
12
@IdanShechter, il serait bon de dire pourquoi vous ne considérez pas cela comme une solution idéale
Omu
2
Le thread peut être problématique, car il ne s'agit pas de HttpRequest, certaines données impliquant HttpRequest peuvent être nulles. Par exemple, HttpRequest .ApplicationPath. Si la tâche est écrite correctement, elle fonctionnera. Un autre problème est le redémarrage du pool d'applications. Si le pool redémarre trop souvent (fuites de mémoire ...), le travailleur ne s'exécutera jamais.
Tomas Kubes
2
Dans le cas où plusieurs instances sont en cours d'exécution (par exemple, l'équilibrage de charge) - vous ne voudriez probablement pas cette solution (plusieurs tâches faisant de même)
Illidan
8

Utilisez le planificateur Windows pour exécuter une page Web.

Pour empêcher les utilisateurs malveillants ou les robots des moteurs de recherche de l'exécuter, lorsque vous configurez la tâche planifiée, il vous suffit d'appeler la page Web avec une chaîne de requête, c'est-à-dire: mypage.aspx? From = scheduletask

Ensuite, dans le chargement de la page, utilisez simplement une condition: if (Request.Querystring ["from"] == "schedtask") {// executetask}

De cette façon, aucune araignée de moteur de recherche ou utilisateur malveillant ne pourra exécuter votre tâche planifiée.

philberg
la source
5
Mieux encore, utilisez un algorithme de hachage salé qui vérifie réellement la chaîne de requête avec un peu plus de sécurité qu'une phrase magique. La demande serait quelque chose comme mypage.aspx? Salt = foo & hash = 1223523jbhdgu13t1. Il vous suffit d'avoir le même algorithme de hachage sur le serveur et le client. Ajoutez également une limite stricte sur le serveur; enregistrer quand il a été exécuté et empêcher l'exécution trop rapide. Je pourrais être paranoïaque cependant.
Nenotlep
14
Encore plus sûr, utilisez Windows Scheduler pour exécuter une page Web qui vérifie si la demande provient du serveur lui-même: Request.IsLocal>> seul le serveur lui-même peut exécuter les tâches planifiées, personne d'autre.
The Conspiracy
Avez-vous plus d'expériences de votre approche? J'allais développer un type de service similaire à notre application et maintenant je ne peux pas décider s'il vaut mieux appeler une page avec une tâche planifiée ou cron, ou si utiliser le système de cache.
JayDee
3

De plus, si votre application utilise SQL SERVER, vous pouvez utiliser l'Agent SQL pour planifier vos tâches. C'est là que nous mettons généralement du code récurrent basé sur les données (rappels par e-mail, maintenance planifiée, purges, etc.). Une excellente fonctionnalité intégrée à l'agent SQL est les options de notification d'échec, qui peuvent vous alerter en cas d'échec d'une tâche critique.

Zachary
la source
2

Je ne sais pas de quel type de tâches planifiées vous parlez. Si vous voulez dire des choses comme "toutes les heures, actualisez les tâches de type foo.xml", utilisez le système de tâches planifiées de Windows. (La commande "at", ou via le contrôleur.) Demandez-lui d'exécuter une application console ou de demander une page spéciale qui démarre le processus.

Modifier: je devrais ajouter, c'est une bonne façon de faire fonctionner votre application IIS aux points planifiés. Supposons donc que vous souhaitiez vérifier votre base de données toutes les 30 minutes et envoyer des rappels par e-mail aux utilisateurs concernant certaines données, vous pouvez utiliser des tâches planifiées pour demander cette page et ainsi obtenir des éléments de traitement IIS.

Si vos besoins sont plus complexes, vous pourriez envisager de créer un service Windows et de le faire exécuter une boucle pour effectuer le traitement dont vous avez besoin. Cela présente également l'avantage de séparer le code à des fins de mise à l'échelle ou de gestion. À la baisse, vous devez gérer les services Windows.

MichaelGG
la source
2

Si vous possédez le serveur, vous devez utiliser le planificateur de tâches Windows. Utilisez AT /? à partir de la ligne de commande pour voir les options.

Sinon, à partir d'un environnement basé sur le Web, vous devrez peut-être faire quelque chose de méchant comme configurer une autre machine pour effectuer des requêtes vers une certaine page sur un intervalle de temps.

t3rse
la source
2

J'ai utilisé Abidar avec succès dans un projet ASP.NET (voici quelques informations générales ).

Le seul problème avec cette méthode est que les tâches ne s'exécuteront pas si l'application Web ASP.NET est déchargée de la mémoire (c'est-à-dire en raison d'une faible utilisation). J'ai essayé de créer une tâche pour frapper l'application Web toutes les 5 minutes, mais cela ne semble pas fonctionner de manière fiable, alors maintenant j'utilise le planificateur Windows et l'application de base pour le faire à la place.

La solution idéale consiste à créer un service Windows, bien que cela ne soit pas possible (par exemple, si vous utilisez un environnement d'hébergement partagé). Cela facilite également les choses du point de vue de la maintenance pour garder les choses dans l'application Web.

Mun
la source
1

Voici une autre façon:

1) Créez un script Web "Heartbeat" qui est responsable du lancement des tâches si elles sont DUE ou en retard pour être lancées.

2) Créez un processus planifié quelque part (de préférence sur le même serveur Web) qui frappe le webscript et le force à s'exécuter à intervalle régulier. (par exemple, la tâche de planification de Windows qui lance silencieusement le script de heatbeat en utilisant IE ou quoi que ce soit)

Le fait que le code de tâche soit contenu dans un script Web est purement dans le but de conserver le code dans la base de code de l'application Web (l'hypothèse est que les deux dépendent les uns des autres), ce qui serait plus facile à gérer pour les développeurs Web. .

L'approche alternative consiste à créer un script / programme de serveur exécutable qui effectue tout le travail de planification lui-même et exécute l'exécutable lui-même en tant que tâche planifiée. Cela peut permettre un découplage fondamental entre l'application Web et la tâche planifiée. Par conséquent, si vous avez besoin que vos tâches planifiées s'exécutent même dans le cas où l'application Web / la base de données pourrait être en panne ou inaccessible, vous devriez opter pour cette approche.

Matias Nino
la source
1
@Matias, pourquoi ne pas laisser le processus planifié faire le vrai travail à la place?
LukeH
1

Vous pouvez facilement créer un service Windows qui exécute du code à intervalle à l'aide de la méthode «ThreadPool.RegisterWaitForSingleObject». Il est vraiment lisse et assez facile à installer. Cette méthode est une approche plus rationalisée que d'utiliser l'un des temporisateurs du cadre.

Jetez un œil au lien ci-dessous pour plus d'informations:

Exécution d'un processus périodique dans .NET à l'aide d'un service Windows:
http://allen-conway-dotnet.blogspot.com/2009/12/running-periodic-process-in-net-using.html

atconway
la source
0

Nous utilisons également des applications de console. Si vous utilisez des outils de journalisation comme Log4net, vous pouvez surveiller correctement leur exécution. De plus, je ne sais pas comment ils sont plus difficiles à maintenir qu'une page Web, étant donné que vous pouvez partager certaines des mêmes bibliothèques de code entre les deux si elles sont conçues correctement.

Si vous ne souhaitez pas que ces tâches soient exécutées de manière chronométrée, vous pouvez avoir une page Web dans votre section administrative de votre site Web qui fait office de file d'attente. L'utilisateur soumet une demande d'exécution de la tâche, à son tour, il insère un enregistrement d'horodatage vierge sur la table MyProcessQueue et votre tâche planifiée vérifie toutes les X minutes pour un nouvel enregistrement dans MyProcessQueue. De cette façon, il ne s'exécute que lorsque le client le souhaite.

J'espère que ces suggestions vous aideront.

Kyle B.
la source
0

Une option serait de configurer un service Windows et de le faire appeler votre tâche planifiée.

Dans les formes de Win que j'ai utilisées, les Timers ne pensent pas que cela fonctionnerait bien dans ASP.NET

AJM
la source
-1

Une nouvelle bibliothèque de classes du planificateur de tâches pour .NET

Remarque: Depuis la création de cette bibliothèque, Microsoft a introduit un nouveau planificateur de tâches (Task Scheduler 2.0) pour Windows Vista. Cette bibliothèque est un wrapper pour l'interface Task Scheduler 1.0, qui est toujours disponible dans Vista et est compatible avec Windows XP, Windows Server 2003 et Windows 2000.

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

Ali
la source
Supprime s'il te plaît. Il a été répondu ci-dessous. Duplicate
Fandango68