【发布时间】: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