运行计划任务的最佳方式

Nie*_*sma 225 windows asp.net iis scheduled-tasks

今天我们构建了一个控制台应用程序,用于运行ASP.NET网站的计划任务.但我认为这种方法有点容易出错且难以维护.如何执行计划任务(在Windows/IIS/ASP.NET环境中)

更新:

任务示例:

  • 从数据库中的电子邮件队列发送电子邮件
  • 从数据库中删除过时的对象
  • 从Google AdWords检索统计信息并填写数据库中的表格.

BC.*_*BC. 128

Jeff Atwood为Stackoverflow提供的这种技术是我遇到过的最简单的方法.它依赖于构建到ASP.NET缓存系统中的"缓存项目已删除"回调机制

更新:Stackoverflow已经超出了这个方法.它只在网站运行时有效,但它是一种非常简单的技术,对很多人都有用.

另请参阅Quartz.NET

  • 我在今天对原始博客文章的评论中注意到了一些事情:"不,我们已经切换到专门的任务.我们肯定超过了这种技术.我认为这对小型网站来说很好!` - 杰夫阿特伍德 (43认同)
  • 那么如果应用程序没有运行会发生什么,但是计划任务需要发生? (12认同)
  • 这太可怕了!任何事情都可能导致应用程序停止运行,它可能只会在下一个用户请求时重新启动.在这些时间之间,你的任务不会运行! (5认同)
  • -1这种方法存在很大的缺陷.每当应用程序被回收时,"CacheItemRemoved"事件将触发,并且您的计划任务将运行.在生产现场,这可能每天发生几次.如果您希望每周运行任务,那就不太好了. (3认同)
  • 如果任务恰好需要一段时间才能运行,这也可能会减慢用户体验.我不希望让用户为我生成维护/任务. (2认同)
  • @Joel 我同意。如果您的服务任务无论应用程序的状态如何都必须运行,这不是正确的方法。在其他情况下,我保留了一个通用服务应用程序模板,它可以帮助我整洁、快速地编写服务。 (2认同)

Bre*_*ski 74

我的所有网站任务(需要安排)都保存在网站内,并从特殊页面调用.然后我写了一个简单的Windows服务,每隔一段时间调用一次这个页面.页面运行后,它返回一个值.如果我知道还有更多的工作要做,我会马上再次运行页面,否则我会在一段时间内运行它.这对我来说非常有效,并且我的所有任务逻辑都与Web代码保持一致.在编写简单的Windows服务之前,我使用Windows调度程序每x分钟调用一次页面.

另一种方便的方法是使用Pingdom等监控服务.将他们的http检查指向运行您的服务代码的页面.让页面返回结果,然后可以用来触发Pingdom在出现问题时发送警报消息.

  • 您是否查看了缓存项目到期技术?我想你会发现它是一个更理想的预定服务实现:http://www.codeproject.com/KB/aspnet/ASPNETService.aspx (16认同)
  • 什么阻止恶意用户(或搜索引擎蜘蛛)调用此页面,从而导致您的计划任务运行? (9认同)
  • 您可以通过在Web应用程序中存储静态时间戳来阻止恶意呼叫,并且仅在尚未设置时间戳(第一次呼叫)或自上次呼叫后正确时间已到期时运行. (8认同)
  • 我通过检查IP地址是否是内部地址来阻止对我的URL的恶意调用.如果它不属于我们组织的内部,它什么也不返回,什么都不做. (5认同)
  • 这是我最终解决的问题.我使用Windows scheduler + curl而不是自定义Web服务.使用Windows服务有什么好处. (3认同)
  • 没有任何好处,这就是你把它放在一起的方式.你的是一个很好的解决方案. (2认同)
  • @user1408767 源IP很容易被欺骗。 (2认同)

Chr*_*tal 30

创建自定义Windows服务.

我将一些任务关键任务设置为计划的控制台应用程序,并发现它们很难维护.我创建了一个带有'heartbeat'的Windows服务,可以每隔几分钟检查一次我的数据库中的计划.它运作得很好.

话虽如此,我仍然使用预定的控制台应用程序来执行大多数非关键维护任务.如果没有损坏,请不要修理它.

  • 仅供参考,链接现已死亡. (7认同)
  • @CharlesBurns,您始终可以通过 archive.org 浏览死链接:https://web.archive.org/web/20090919131944/http://www.dotheweb.net/articles/dotnet/services.aspx (2认同)

Dan*_*ger 17

我发现所有参与者都很容易:

  • 创建Web服务方法,例如DoSuchAndSuchProcess
  • 创建一个调用此web方法的控制台应用程序.
  • 在任务计划程序中安排控制台应用程序.

使用此方法,所有业务逻辑都包含在您的Web应用程序中,但您具有Windows任务管理器或任何其他商业任务管理器的可靠性,可以将其启动并记录任何返回信息(如执行报告).使用Web服务而不是发布到页面有一些优势,因为它更容易从Web服务返回数据.


小智 9

为什么重新发明轮子,使用线程和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
    }
Run Code Online (Sandbox Code Playgroud)

  • @IdanShechter告诉你为什么认为这不是一个理想的解决方案会很好 (12认同)
  • 你不需要生成一个线程来启动一个计时器...... (7认同)
  • 我也认为这不是一个理想的解决方案. (4认同)
  • 线程可能有问题,因为它不是HttpRequest,一些涉及HttpRequest的数据可以为null.例如HttpRequest .ApplicationPath.如果任务写得正确,它将起作用.另一个问题是应用程序池重新启动.如果池太频繁重启(内存泄漏......),工作人员将永远不会运行. (2认同)
  • 如果你有几个实例运行(例如负载平衡) - 可能你不会想要这个解决方案(几个任务做同样的事情) (2认同)

小智 8

使用Windows Scheduler运行网页.

为防止恶意用户或搜索引擎蜘蛛运行它,在设置计划任务时,只需使用查询字符串调用网页,即:mypage.aspx?from = scheduledtask

然后在页面加载中,只需使用一个条件:if(Request.Querystring ["from"] =="scheduledtask"){// executetask}

这样,搜索引擎蜘蛛或恶意用户就无法执行您的计划任务.

  • 更安全的是,使用Windows Scheduler运行一个网页,检查请求是否来自服务器本身:`Request.IsLocal` >>只有服务器本身可以运行计划任务,没有其他人. (14认同)
  • 更好的是,使用salted哈希算法实际验证查询字符串的安全性比魔术短语更高.req会像mypage.aspx?salt = foo&hash = 1223523jbhdgu13t1.您只需要在服务器和客户端上使用相同的哈希算法.还要在服务器上添加硬限制; 执行时保存,防止执行过快.我可能是偏执狂. (5认同)