使用Quartz.NET进行MVC3 webapp任务调度

时间:2012-06-29 12:45:46

标签: c# .net asp.net-mvc quartz.net .net-remoting

我需要您的建议来安排MVC3 Webapp中的任务。

我的任务是为webapp中的不同服务创建一些通用调度程序,以便稍后在开发中使用。例如,我们有一些可用的任务,用户可以随时安排。

我不想重新发明轮子并找到可用于创建调度程序的Quartz.Net库。

我知道在webapp中托管调度不是一个好主意,因为webserver可以回收应用程序池等,所以我决定在Windows服务中使用它,然后使用Quartz.NET远程处理功能来触发我的webapp中的任务

但我发现了一些问题。如果我错了,请纠正我,但是当我尝试使用Quartz.NET远程处理它在Windows服务进程中运行时,这意味着它需要知道我的webapp中的所有类型,所以webapp的所有程序集应该引用它,我需要有另一个数据库等的配置文件。所以如果我写新的工作类,我不能轻松安排它,我需要停止服务并为它更新库,所以这不是一般的方法。

我找不到Quartz.NET只能根据它的界面运行作业的任何信息。

所以我想出了自己的调度程序,它将在Windows服务中托管,并且将有一些将在webapp中实现的IJob接口。我还将使用IPC通道使用.Net远程处理。 所以webapp就像.Net Remoting Server,当我想添加一些新工作然后安排它时,我将只需要编写实现IJob接口的新工作。 我将其注册为

        IpcChannel channel = new IpcChannel("CurrentIPC");

        ChannelServices.RegisterChannel(channel);

        RemotingConfiguration.RegisterWellKnownServiceType(
            typeof(SimpleJob), "SimpleJob", WellKnownObjectMode.SingleCall);
        RemotingConfiguration.RegisterWellKnownServiceType(
            typeof(ComplexObject), "ComplexObject", WellKnownObjectMode.SingleCall);

在这种情况下,我将注册两种作业类型。然后在调度作业时,我将传递类的名称,并在Windows服务端代表客户端(在webapp端执行对象),我将使用IJob将类的传递名称绑定为:

Dictionary<string, IJob> jobs = new Dictionary<string, IJob>();
    void AddJob(string name)
    {
        IJob obj = (IJob)Activator.GetObject(typeof(IJob), string.Format("ipc://CurrentIPC/{0}", name));
        jobs.Add(name, obj);
    }

所以现在我不需要打扰我的应用程序和其他东西的引用,调度程序将在不知道任何事情的情况下完成它的工作,只需要IJob接口并在webapp端执行任务。

如果我错了,或者它太复杂了,还有一些其他更简单的方法可以做到这一点,或者有一些我不知道的陷阱,你能帮助我吗? 谢谢。

P.S。 还有一个想法是让单独的调度程序直接通过执行Web应用程序中指定服务的链接来运行Web应用程序方法,例如“http:// localhost:3030 / Request / 12”,这就是全部,但是在我的网络应用程序中,您应该被授权执行此类请求,并且我们还需要解决我们需要解决的问题,如果有数千个计划任务,我们将对网络服务器进行额外加载。

5 个答案:

答案 0 :(得分:2)

我认为你走在正确的轨道上,我会使用Quartz.NET创建调度程序并将其托管在Windows服务中,因为应用程序池回收问题。

它将使用特定的URL触发您的webapp中的任务/服务:s用于您的Web应用程序或单独的Web服务实例中的每个任务/服务。

使用此分隔,调度程序只需要知道网址和日程安排,而无需直接引用您的应用程序。这也可以在未来的项目中重复使用。

答案 1 :(得分:1)

  

我知道在webapp中托管调度并不是一个好主意,因为webserver可以回收应用程序池等,所以我决定在Windows服务中使用它 ......

为何复杂化?为什么不简化并使用外部服务在一段时间内运行webhook?

我使用这项服务并且我很开心,虽然我可以根据这个简单的程序创建自己的服务这么容易:

  

http://momentapp.com/

简化通话:

private void Run() {
     try {
        var work = RequestNewMessage();  // get work
        ProcessWork(work);  // process work
        // Log work 
     }
     catch(Exception ex) {
        // Log Error
     }
     finally {
        // set job for now plus1 minute
        SetRecuringJob(DateTime.UtcNow.AddMinute(1)); 
     }
}

private void SetRecuringJob(DateTime dt) {
    PostJob("https://momentapp.com/jobs/new?job[at]={0:s}&job[method]=POST&job[uri]=http://yourapp.com/", dt);
}

答案 2 :(得分:1)

我想象的有点晚,但对其他人来说仍然有用。

这是一个我用了很长时间的项目似乎满足了大多数要求 - 事实上,我几乎专门用于问题中描述的回调作业。它也是我们内部使用的,所以我尽量保持更新。

http://backgroundworker.codeplex.com/

它非常类似于Quartz,但更专注于管理工作及其数据。

答案 3 :(得分:0)

如果您的问题是您不希望从WindowService引用整个Web应用程序,并且我同意这一点,那么为什么不简单地创建一个实用通用作业的实用程序dll,能够通过以下方式调用您的Web应用程序plain http url并将“actions”实现为WCF REST服务? 我认为这将清理一下架构,并保持组织中的调度程序服务的隔离(和可重用)。

答案 4 :(得分:0)

我可能错过了一项要求,但由于您似乎能够安装自定义服务,听起来您可以完全控制该计算机。因此,您可以为重复性工作安排Windows任务,这应该为重复性任务提供非常可靠的基础。

然后,您可以安排VB脚本及时加载网址,例如:http://4rapiddev.com/internet/call-or-open-a-web-page-url-by-using-windows-task-scheduler-or-cronjob/

当然,从批处理文件,从powershell到自定义可执行文件都是如此。

这种方法的好处:

  • 您可以依赖操作系统擅长的默认操作系统行为:安排:)
  • 管理员已经有了一个用户界面(虽然不是网络用户界面)
  • 你没有依赖,但操作系统

可能的缺点:

编辑:我似乎错过了身份验证的要求,但是当您使用Windows时,您可以允许在应用的某个区域内进行Windows身份验证。并且因为您正在使用 Windows身份验证的计划任务,所以您可以使用此功能。我从未在ASP.NET应用程序中大量使用Windows身份验证,但您甚至可能只使用自定义配置而无需额外编程。