[英]Needed: A Windows Service That Executes Jobs from a Job Queue in a DB; Wanted: Example Code
Needed: 需要:
Wanted: 通缉:
Background: 背景:
Emphasis: 重点:
Given that you are dealing with a database queue, you have a fair cut of the job already done for you due to the transactional nature of databases. 鉴于您正在处理数据库队列,由于数据库的事务性质,您已经为您完成了相当多的工作。 Typical queue driven application has a loop that does:
典型的队列驱动应用程序具有一个循环,该循环执行:
while(1) {
Start transction;
Dequeue item from queue;
process item;
save new state of item;
commit;
}
If processing crashes midway, the transaction rolls back and the item is processed on the next service start up. 如果处理中途崩溃,则事务将回滚,并且在下一次服务启动时将处理该项目。
But writing queues in a database is actually a lot trickier than you believe. 但实际上,在数据库中写入队列是很多棘手比你相信。 If you deploy a naive approach, you'll find out that your enqueue and dequeue are blocking each other and the ashx page becomes unresponsive.
如果您采用幼稚的方法,您会发现入队和出队是相互阻塞的,并且ashx页面变得无响应。 Next you'll discover the dequeue vs. dequeue are deadlocking and your loop is constantly hitting error 1205. I strongly urge you to read this article Using Tables as Queues .
接下来,您将发现出队列与出队列处于死锁状态,并且循环不断遇到错误1205。我强烈建议您阅读本文“ 将表用作队列” 。
Your next challenge is going to be getting the pooling rate 'just right'. 您的下一个挑战将是使池化速率“恰到好处”。 Too aggressive and your database will be burning hot from the pooling requests.
过于激进,您的数据库将因池化请求而变得炙手可热。 Too lax and your queue will grow at rush hours and will drain too slowly.
太松懈,您的队列将在高峰时间增长,并且流失得太慢。 You should consider using an entirely different approach: use a SQL Server built-in
QUEUE
object and rely on the magic of the WAITFOR(RECEIVE)
semantics. 您应该考虑使用完全不同的方法:使用SQL Server内置的
QUEUE
对象,并依靠WAITFOR(RECEIVE)
语义的魔力。 This allows for completely poll free self load tuning service behavior. 这允许完全无轮询的自负载调整服务行为。 Actually, there is more: you don't need a service to start with.
实际上,还有更多:您不需要任何服务。 See Asynchronous Procedures Execution for an explanation on what I'm talking about: launching processing asynchronously in SQL Server from a web service call, in a completely reliable manner.
有关我正在谈论的内容的说明,请参见异步过程执行 :以完全可靠的方式从Web服务调用在SQL Server中异步启动处理。 And finally, if the logic must be in C# process then you can leverage the External Activator , which allows the processing to be hosted in standalone processes as opposed to T-SQL procedures.
最后,如果逻辑必须在C#进程中,则可以利用External Activator ,它允许将处理托管在独立的进程中,而不是T-SQL过程。
First you'll need to consider 首先,您需要考虑
Implementation 实作
Here's the basic framework of all those ideas. 这是所有这些想法的基本框架。 It includes a way to debug this which is a pain
它包括一种调试方法,这很痛苦
public partial class Service : ServiceBase{
System.Timers.Timer timer;
public Service()
{
timer = new System.Timers.Timer();
//When autoreset is True there are reentrancy problme
timer.AutoReset = false;
timer.Elapsed += new System.Timers.ElapsedEventHandler(DoStuff);
}
private void DoStuff(object sender, System.Timers.ElapsedEventArgs e)
{
Collection stuff = GetData();
LastChecked = DateTime.Now;
foreach (Object item in stuff)
{
try
{
item.Dosomthing()
}
catch (System.Exception ex)
{
this.EventLog.Source = "SomeService";
this.EventLog.WriteEntry(ex.ToString());
this.Stop();
}
TimeSpan ts = DateTime.Now.Subtract(LastChecked);
TimeSpan MaxWaitTime = TimeSpan.FromMinutes(5);
if (MaxWaitTime.Subtract(ts).CompareTo(TimeSpan.Zero) > -1)
timer.Interval = MaxWaitTime.Subtract(ts).TotalMilliseconds;
else
timer.Interval = 1;
timer.Start();
}
protected override void OnPause()
{
base.OnPause();
this.timer.Stop();
}
protected override void OnContinue()
{
base.OnContinue();
this.timer.Interval = 1;
this.timer.Start();
}
protected override void OnStop()
{
base.OnStop();
this.timer.Stop();
}
protected override void OnStart(string[] args)
{
foreach (string arg in args)
{
if (arg == "DEBUG_SERVICE")
DebugMode();
}
#if DEBUG
DebugMode();
#endif
timer.Interval = 1;
timer.Start();
}
private static void DebugMode()
{
Debugger.Break();
}
}
EDIT Fixed loop in Start() 编辑 Start()中的固定循环
EDIT Turns out Milliseconds is not the same as TotalMilliseconds 编辑结果毫秒与TotalMilliseconds不同
You may want to have a look at Quartz.Net to manage scheduling the jobs. 您可能需要查看Quartz.Net来管理计划作业。 Not sure if it will fit your particular situation, but it's worth a look.
不知道它是否适合您的特定情况,但是值得一看。
Some things I can think of, based on your edit: 根据您的修改,我可以想到一些事情:
Re: job failure: 回复:工作失败:
Re: contention: 回复:争用:
Re: keeping the service running 回复:保持服务运行
I'm really just poking around in the dark here. 我真的只是在这里黑暗中闲逛。 I'd strongly suggest prototyping the service and returning with any specific questions about the way it functions.
我强烈建议对服务进行原型设计,并返回有关其运行方式的任何特定问题。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.