2012-06-29 32 views
3

我需要您的建议来安排MVC3 Webapp中的任务。使用Quartz.NET的MVC3 webapp任务调度

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

我不想重新发明轮子,并找到可用于创建调度程序的Quartz.Net库。我知道这是不是一个好主意,主持调度内部Web应用程序原因Web服务器可以回收应用程序池等,所以我决定在Windows服务中使用它,然后使用Quartz.NET远程处理功能来触发我内部的任务Web应用程序。

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

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

所以我想出了一个想法,写我自己的调度程序,它将被托管在Windows服务中,并且将有一些IJob接口将在webapp中实现。我还将使用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服务端的类和名字,将代表客户机(在web应用端执行的对象),我将只是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接口和web应用程序端执行的任务。

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

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

回答

2

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

它会触发使用特定的URL任务/在你的web应用服务:■每个任务/服务无论是在你的web应用程序或一个单独的Web服务实例。

使用这种分离的调度程序只需要知道的网址和日程表,并不需要直接引用您的应用程序。这在未来的项目中也是可重用的。

+0

如果选择了这种方法,可能会出现另一个问题。并发 - 调用相同的作业url将触发两个作业执行。如果是电子邮件,您可能会最终发送两封相同的电子邮件。 –

+1

这是真的,如果这是一个问题,那么可能需要一些安全措施,或者在调度程序中假定url唯一标识作业实例或可能在作业中,假设作业能够识别类似作业正在运行或已经完成。 –

1

我知道,这不是托管Web应用程序的网络服务器事业里面调度可以回收应用程序池,等一个好主意,,所以我决定用它的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); 
} 
0

如果你的问题是你不希望从WindowService引用整个web应用程序,我同意这一点,你为什么不干脆创建一个实用程序DLL实现能够通过打电话给你的web应用程序的通用工作一个普通的http url并将WCF REST服务实现为“操作”? 这个我认为将清理了一下架构,并保持绝缘的(和可重复使用)调度服务在您的组织。

0

我可能会丢失的要求,但你似乎能够安装的定制服务,这听起来像你有过这台机器的完全控制。所以你不妨为你的定期任务安排一个Windows任务,这将为你重复执行任务提供一个非常坚实的基础。

可以安排一个VB脚本加载URL的及时,喜欢这里:http://4rapiddev.com/internet/call-or-open-a-web-page-url-by-using-windows-task-scheduler-or-cronjob/

什么都可以,当然,从批处理文件,在PowerShell来定制的可执行文件。

上升空间,以这种方式:

  • 你可以依靠默认的操作系统行为什么操作系统擅长:调度:)
  • 有已经为管理员的UI(尽管不是一个Web UI)
  • 你有没有依赖性,但OS

可能的缺点:

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

1

有点晚我想象,但仍然可以为其他人有用。

这是一个我花了相当一段时间的项目,似乎满足了大多数要求 - 事实上,我几乎全部用于回调作业,如问题中所述。这也是我们内部使用的,所以我会尽量保持更新。

http://backgroundworker.codeplex.com/

这是非常类似石英,但对管理工作和他们的数据更集中。