我需要您的建议来安排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”,这就是全部,但是在我的网络应用程序中,您应该被授权执行此类请求,并且我们还需要解决我们需要解决的问题,如果有数千个计划任务,我们将对网络服务器进行额外加载。
答案 0 :(得分:2)
我认为你走在正确的轨道上,我会使用Quartz.NET创建调度程序并将其托管在Windows服务中,因为应用程序池回收问题。
它将使用特定的URL触发您的webapp中的任务/服务:s用于您的Web应用程序或单独的Web服务实例中的每个任务/服务。
使用此分隔,调度程序只需要知道网址和日程安排,而无需直接引用您的应用程序。这也可以在未来的项目中重复使用。
答案 1 :(得分:1)
我知道在webapp中托管调度并不是一个好主意,因为webserver可以回收应用程序池等,所以我决定在Windows服务中使用它 ......
为何复杂化?为什么不简化并使用外部服务在一段时间内运行webhook?
我使用这项服务并且我很开心,虽然我可以根据这个简单的程序创建自己的服务这么容易:
简化通话:
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身份验证,但您甚至可能只使用自定义配置而无需额外编程。