Melhor maneira de executar tarefas agendadas [fechado]

229

Hoje, criamos um aplicativo de console para executar as tarefas agendadas em nosso site ASP.NET. Mas acho que essa abordagem é um pouco propensa a erros e difícil de manter. Como você executa sua tarefa agendada (em um ambiente Windows / IIS / ASP.NET)

Atualizar:

Exemplos de tarefas:

  • Enviando email de uma fila de email no banco de dados
  • Removendo objetos desatualizados do banco de dados
  • Recuperando estatísticas do Google AdWords e preencha uma tabela no banco de dados.
Niels Bosma
fonte
Qual é um exemplo das tarefas que você está executando?
10119 JeffO
4
Você precisa verificar atrigger.com
Kousha
Se você tem Plesk você pode escrever uma vbs e ad-lo para o Agendador de Tarefas: net24.co.nz/kb/article/AA-00213/13/Shared-Hosting/ASP-ASP.NET/...
Hasang

Respostas:

74

Todas as minhas tarefas (que precisam ser agendadas) para um site são mantidas no site e chamadas a partir de uma página especial. Em seguida, escrevi um serviço simples do Windows que chama essa página de vez em quando. Depois que a página é executada, ele retorna um valor. Se eu sei que há mais trabalho a ser feito, eu corro a página novamente, imediatamente, caso contrário eu corro daqui a pouco. Isso funcionou muito bem para mim e mantém toda a minha lógica de tarefas com o código da web. Antes de escrever o serviço simples do Windows, usei o agendador do Windows para chamar a página a cada x minutos.

Outra maneira conveniente de executar isso é usar um serviço de monitoramento como o Pingdom . Aponte a verificação http para a página que executa seu código de serviço. Faça com que a página retorne resultados que podem ser usados ​​para acionar o Pingdom para enviar mensagens de alerta quando algo não estiver certo.

Brettski
fonte
3
Esta é a solução que eu acabei com. Em vez de um serviço da Web personalizado, eu uso o Windows Scheduler + Curl. Qual é a vantagem de usar um serviço do Windows.
Niels Bosma
16
Você já olhou para a técnica de expiração do item de cache? Eu acho que você vai descobrir que ele é uma implementação muito mais ideal de um serviço regular: codeproject.com/KB/aspnet/ASPNETService.aspx
Richard Clayton
10
O que impede um usuário mal-intencionado (ou uma aranha de mecanismo de pesquisa) de chamar esta página e, assim, executar suas tarefas agendadas?
UpTheCreek 3/11/2009
8
Você pode interromper chamadas maliciosas armazenando um carimbo de data / hora estático no aplicativo Web e executando apenas se o carimbo de data / hora não tiver sido definido (primeira chamada) ou se o tempo correto expirou desde a última chamada.
Rob Kent
5
Paro chamadas maliciosas ao meu URL, verificando se o endereço IP é um endereço interno ou não. Ele não retorna nada e não faz nada se não for interno à nossa organização.
User1408767
128

Essa técnica de Jeff Atwood para Stackoverflow é o método mais simples que já encontrei. Ele se baseia no mecanismo de retorno de chamada "item de cache removido" incorporado ao sistema de cache do ASP.NET

Atualização: o Stackoverflow superou esse método. Funciona apenas enquanto o site está sendo executado, mas é uma técnica muito simples que é útil para muitas pessoas.

Verifique também o Quartz.NET

BC.
fonte
12
Então, o que acontece se o aplicativo não estiver em execução, mas a tarefa agendada precisa acontecer?
22909 MichaelGG
2
Isso também pode diminuir a experiência do usuário se a tarefa demorar um pouco para ser executada dessa vez. Prefiro não fazer com que o usuário crie minhas tarefas / manutenção para mim.
1859 Brettski
5
Isso é assustador como o inferno! Qualquer coisa pode fazer com que o aplicativo pare de ser executado e provavelmente apenas reinicie na próxima solicitação do usuário. Entre esses momentos, suas tarefas não são executadas!
teedyay
43
Algo que notei hoje nos comentários da postagem original do 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 Existe uma grande falha nessa abordagem. Sempre que o aplicativo é reciclado, o evento 'CacheItemRemoved' é acionado e sua tarefa agendada será executada. Nos locais de produção, isso pode acontecer algumas vezes ao dia. Não é tão bom se você deseja que a tarefa seja executada semanalmente.
Steven de Salas
30

Crie um serviço personalizado do Windows .

Eu tinha algumas tarefas críticas configuradas como aplicativos de console agendados e achava difícil mantê-las. Criei um serviço do Windows com um 'batimento cardíaco' que verificaria uma agenda no meu banco de dados a cada dois minutos. Funcionou muito bem.

Dito isto, ainda uso aplicativos de console agendados para a maioria das minhas tarefas de manutenção não críticas. Se não estiver quebrado, não conserte.

Chris Van Opstal
fonte
7
Para sua informação, o link está morto.
Charles Burns
1
@CharlesBurns, você sempre pode navegar links mortos com archive.org: web.archive.org/web/20090919131944/http://www.dotheweb.net/...
Nikolay Kostov
17

Eu achei isso fácil para todos os envolvidos:

  • Crie um método de serviço da web, como DoSuchAndSuchProcess
  • Crie um aplicativo de console que chama esse método da web.
  • Agende o aplicativo de console no agendador de tarefas.

Usando essa metodologia, toda a lógica de negócios está contida no aplicativo da Web, mas você tem a confiabilidade do gerenciador de tarefas do Windows ou de qualquer outro gerenciador de tarefas comercial para iniciar e registrar qualquer informação de retorno, como um relatório de execução. Usar um serviço da Web em vez de postar em uma página tem uma vantagem, porque é mais fácil obter dados de retorno de um serviço da Web.

Daniel Auger
fonte
10

Por que reinventar a roda, use as classes 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
    }
Moisés Gonçalves
fonte
7
Você não precisa gerar um segmento para iniciar um temporizador ...
Zyo
4
Eu também não acho que seja uma solução ideal.
Idan Shechter
12
@IdanShechter que seria bom para contar uma razão para que você considere isto não é uma solução ideal
Omu
2
O encadeamento pode ser problemático, porque não é HttpRequest, alguns dados que envolvem HttpRequest podem ser nulos. Por exemplo, HttpRequest .ApplicationPath. Se a tarefa for escrita corretamente, ela funcionará. Outro problema é a reinicialização do pool de aplicativos. Se o pool for reiniciado com muita frequência (vazamentos de memória ...), o trabalhador nunca será executado.
Tomas Kubes
2
No caso de você ter várias instâncias em execução (por exemplo, balanceamento de carga) - provavelmente você não iria querer esta solução (várias tarefas fazendo o mesmo)
Illidan
8

Use o Windows Scheduler para executar uma página da web.

Para impedir que o usuário malicioso ou as aranhas do mecanismo de pesquisa executem, quando você configura a tarefa agendada, basta chamar a página da Web com uma string de consulta, ou seja: mypage.aspx? From = scheduletask

Em seguida, no carregamento da página, basta usar uma condição: if (Request.Querystring ["from"] == "scheduletask") {// executetask}

Dessa forma, nenhum mecanismo de busca ou usuário mal-intencionado poderá executar sua tarefa agendada.

philberg
fonte
5
Melhor ainda, use um algoritmo de hash salgado que realmente verifique a string de consulta com um pouco mais de segurança do que uma frase mágica. O req seria algo como mypage.aspx? Salt = foo & hash = 1223523jbhdgu13t1. Você só precisa ter o mesmo algoritmo de hash no servidor e no cliente. Adicione também um limite rígido no servidor; salve quando foi executado e impeça a execução muito rápida. Eu posso ser paranóico embora.
Nenotlep 31/07
14
Ainda mais seguro, use o Windows Scheduler para executar uma página da Web que verifique se a solicitação é proveniente do próprio servidor: Request.IsLocal>> apenas o próprio servidor pode executar as tarefas agendadas, mais ninguém.
A Conspiração
Você tem mais experiências com sua abordagem? Iria desenvolver um tipo de serviço semelhante ao nosso aplicativo e agora não consigo decidir se é melhor chamar uma página com tarefa agendada ou cron, ou se usar o sistema de cache.
JayDee
3

Além disso, se seu aplicativo usa o SQL SERVER, você pode usar o SQL Agent para agendar suas tarefas. É aqui que geralmente colocamos códigos recorrentes que são orientados por dados (lembretes por email, manutenção agendada, limpezas, etc ...). Um ótimo recurso incorporado ao SQL Agent são as opções de notificação de falha, que podem alertá-lo se uma tarefa crítica falhar.

Zachary
fonte
2

Não sei ao certo que tipo de tarefas agendadas você quer dizer. Se você quiser coisas como tarefas a cada hora, atualize foo.xml, use o sistema Tarefas agendadas do Windows. (O comando "at" ou por meio do controlador.) Execute um aplicativo de console ou solicite uma página especial que inicie o processo.

Editar: devo acrescentar que esta é uma maneira OK de também executar o aplicativo IIS em pontos agendados. Portanto, suponha que você queira verificar seu banco de dados a cada 30 minutos e enviar lembretes por e-mail aos usuários sobre alguns dados, você pode usar tarefas agendadas para solicitar esta página e, portanto, obter o IIS processando as coisas.

Se suas necessidades forem mais complexas, considere criar um serviço do Windows e executá-lo em um loop para fazer o processamento necessário. Isso também tem o benefício de separar o código para fins de dimensionamento ou gerenciamento. No lado negativo, você precisa lidar com os serviços do Windows.

MichaelGG
fonte
2

Se você possui o servidor, use o agendador de tarefas do Windows. Use AT /? na linha de comando para ver as opções.

Caso contrário, em um ambiente baseado na Web, talvez você precise fazer algo desagradável, como configurar uma máquina diferente para fazer solicitações para uma determinada página em um intervalo de tempo.

t3rse
fonte
2

Eu usei o Abidar com sucesso em um projeto ASP.NET (aqui estão algumas informações básicas ).

O único problema com esse método é que as tarefas não serão executadas se o aplicativo Web do ASP.NET for descarregado da memória (ou seja, devido ao baixo uso). Uma coisa que tentei é criar uma tarefa para acessar o aplicativo da Web a cada 5 minutos, mantendo-o ativo, mas isso não parecia funcionar de maneira confiável, então agora estou usando o agendador do Windows e o aplicativo básico do console para fazer isso.

A solução ideal é criar um serviço do Windows, embora isso possa não ser possível (por exemplo, se você estiver usando um ambiente de hospedagem compartilhado). Isso também facilita um pouco as coisas da perspectiva da manutenção para manter as coisas dentro do aplicativo da web.

Mun
fonte
1

Aqui está outra maneira:

1) Crie um script da web de "pulsação" que seja responsável por iniciar as tarefas se elas estiverem DEVIDAS ou atrasadas para serem ativadas.

2) Crie um processo agendado em algum lugar (de preferência no mesmo servidor da web) que atinja o script da web e o force a executar em um intervalo regular. (por exemplo, o Windows agenda tarefas que silenciosamente iniciam o script heatbeat usando IE ou whathaveyou)

O fato de o código da tarefa estar contido em um script da Web é apenas para manter o código dentro base de código do aplicativo da Web (a suposição é de que ambos dependem um do outro), o que seria mais fácil para os desenvolvedores da Web gerenciarem .

A abordagem alternativa é criar um script / programa de servidor executável que faça todo o agendamento funcionar sozinho e execute o executável como uma tarefa agendada. Isso pode permitir a dissociação fundamental entre o aplicativo Web e a tarefa agendada. Portanto, se você precisar que suas tarefas agendadas sejam executadas mesmo que o aplicativo / banco de dados da web esteja inativo ou inacessível, siga essa abordagem.

Matias Nino
fonte
1
@ Matias, Por que não apenas o processo agendado faz o trabalho real?
21410 LukeH
1

Você pode criar facilmente um Serviço do Windows que executa o código em intervalos usando o método 'ThreadPool.RegisterWaitForSingleObject'. É realmente liso e muito fácil de configurar. Esse método é uma abordagem mais simplificada do que usar qualquer um dos Timers no Framework.

Dê uma olhada no link abaixo para obter mais informações:

Executando um processo periódico no .NET usando um serviço do Windows:
http://allen-conway-dotnet.blogspot.com/2009/12/running-periodic-process-in-net-using.html

atconway
fonte
0

Também usamos aplicativos de console. Se você usar ferramentas de log como o Log4net, poderá monitorar adequadamente sua execução. Além disso, não tenho certeza de como eles são mais difíceis de manter do que uma página da Web, pois você pode compartilhar algumas das mesmas bibliotecas de código entre as duas, se ela tiver sido projetada corretamente.

Se você é contra a execução periódica dessas tarefas, você pode ter uma página da web na seção administrativa do site que atua como uma fila. O usuário solicita a execução da tarefa, insere um registro de carimbo de data / hora em branco na tabela MyProcessQueue e sua tarefa agendada verifica todos os X minutos para um novo registro em MyProcessQueue. Dessa forma, ele só é executado quando o cliente deseja que ele seja executado.

Espero que essas sugestões ajudem.

Kyle B.
fonte
0

Uma opção seria configurar um serviço do Windows e fazer com que ele chamasse sua tarefa agendada.

Nas winforms que usei Timers, não acho que isso funcionaria bem no ASP.NET

AJM
fonte
-1

Uma nova biblioteca de classes do Agendador de tarefas para .NET

Nota: Desde que essa biblioteca foi criada, a Microsoft introduziu um novo agendador de tarefas (Task Scheduler 2.0) para Windows Vista. Esta biblioteca é um invólucro para a interface do Agendador de Tarefas 1.0, que ainda está disponível no Vista e é compatível com o Windows XP, Windows Server 2003 e Windows 2000.

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

Todos
fonte
Por favor delete. Foi respondido abaixo. Duplicar
Fandango68