【问题标题】:MVC3 webapp task scheduling with Quartz.NET使用 Quartz.NET 进行 MVC3 webapp 任务调度
【发布时间】:2012-06-29 12:45:46
【问题描述】:

在 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 端执行任务。

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

附: 还有一个想法是有一个单独的调度程序,它将通过在 Web 应用程序中执行指向指定服务的链接来直接运行 Web 应用程序方法,例如“http://localhost:3030/Request/12”,仅此而已,但在我的网络应用程序,你应该被授权执行这样的请求,我们有问题需要解决,如果有数千个计划任务,我们将通过这样的请求向网络服务器增加额外的负载。

【问题讨论】:

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


    【解决方案1】:

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

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

    使用这种分离,调度程序只需要知道 url 和调度,而不需要直接引用您的应用程序。这也可以在未来的项目中重复使用。

    【讨论】:

    • 如果选择这种方法,可能会出现另一个问题。并发 - 调用相同的作业 url 将触发两个作业执行。如果是电子邮件,您可能会发送两次相同的电子邮件。
    • 这是真的,如果这是一个问题,则可能需要在调度程序中采取一些保护措施,假设 url 唯一标识作业实例,或者可能在作业中,假设作业能够识别类似的作业正在运行或已经完成。
    【解决方案2】:

    我知道在 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);
    }
    

    【讨论】:

      【解决方案3】:

      我想有点晚了,但对其他人仍然有用。

      这是一个我花了很多时间完成的项目,它似乎满足了大部分的要求——事实上,我几乎只将它用于问题中描述的回调工作。这也是我们内部使用的,所以我会尽量保持更新。

      http://backgroundworker.codeplex.com/

      它与 Quartz 非常相似,但更侧重于管理作业及其数据。

      【讨论】:

        【解决方案4】:

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

        【讨论】:

          【解决方案5】:

          我可能遗漏了一项要求,但由于您似乎能够安装自定义服务,听起来您可以完全控制该机器。因此,您不妨为您的重复作业安排一个 Windows 任务,这应该为您重复执行的任务提供一个非常坚实的基础。

          然后您可以安排一个 VB 脚本来及时加载一个 url,如下所示: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 身份验证,但您甚至可以只使用自定义配置而无需额外编程。

          【讨论】:

            猜你喜欢
            • 2017-06-02
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2013-02-01
            相关资源
            最近更新 更多