最近在搞一个新的项目,其中有一个需求涉及定时任务。 具体需求如下: 在服务器的数据库中有1000-10000个用户,每个用户有100个产品(假设),每个用户都可以设置开启定时任务的开关,并且可以设置定时时间,和定时的产品。 通过以上的设置,系统需要根据用户设定的结果对其产品进行一系列操作,例如修改产品的名称。 具体需求就是这样的,有哪位有好的思路希望跟大家交流一下,谢谢
说下我的看法吧。
1、WEB界面只做设置用,设置后的数据保存在XML或是数据库中。
2、创建一个Window Service,定时检查(每分钟检查一次之类的)是否有设置符合时间要求,
如果符合,则执行相关的处理。
主要要注意的是这些用户的数据是否会有交集,没有的话难度就小很多了。
window Service昨天做好了,有一点比较有疑问:我需要的是多个任务同时进行,而且配置的定时时间都是直接从数据库中读取的,不同的产品不同的定时时间,都是可变的
@ganzhushangjia:
何谓多任务?
你把读取时间比较放在主线程。发现需要运行的任务,就抛一个线程去运行好了。
然后下一个时钟到达,还是这样检查, r u see?
@爱编程的大叔: 但这个有个缺点,不是实时的,如何做到asp.net程序跟windows service通讯,把用户的请求发送给它。
@ganzhushangjia:
用户请求需要马上看到结果?假的啦,这都是程序员大叔骗小妹妹的方法。
你在请求数据表中放一个字段,TRUE/FALSE,TRUE表示小妹妹我帮你处理过了。
ASP.NET就去检查这个数据,发现为真,跳转到一个页面,否则就一直
I being waiting....
for the girl like you.
至于实时,你把Service的时钟调快一点就行了,比如每100MS检查一次之类的。
程序员的世界里面,啥都是假假的啦,要棒棒糖就new一个。
@爱编程的大叔: socket可信不
定时任务最好不要放IIS要弄也要单独放一个,不然会有IIS自动回收问题.
单独写个服务处理这个吧
话说有人提议让我用sql作业去完成这问题,好像可以实现,但不太明白创建作业的个数等限制问题,后期用户量大了,怕服务器扛不住
@ganzhushangjia: 这种东西sql作业是可以实现的,但最好不要.扩展性可维护性都不是不好,是不存在...
你写个win服务比较好
Quatz.Net,可是试试~
写个Windows服务最好
这个问题无论是哪种解决办法,最终都是对数据的处理,那么最快最好肯定就是SQL计划作业,你把业务写成存储过程,用计划作业调用它,是比较可行简单。存储过程有个问题就是维护麻烦,如果业务复杂你就写成服务吧。
sql计划作业不知道其稳定性怎么样。 我需要的是多个任务同时进行,而且配置的定时时间都是直接从数据库中读取的,不同的产品不同的定时时间,都是可变的,如果一个产品就生成一个计划,那数据库会卡出翔
比较赞同用quatz.net
可以参考网上大部分的论坛discuz NT的源码(网上可以下),在httpModule.cs中.简化一个就是这样
static Timer eventTimer; /// <summary> /// 实现接口的Init方法 /// </summary> /// <param name="context"></param> public void Init(HttpApplication context) { //DNT的计划任务 if (eventTimer == null && ScheduleConfigs.GetConfig().Enabled) { eventTimer = new Timer(new TimerCallback(ScheduledEventWorkCallback), context.Context, 60000, EventManager.TimerMinutesInterval * 60000); } } private void ScheduledEventWorkCallback(object sender) { try { if (ScheduleConfigs.GetConfig().Enabled) { EventManager.Execute(); } } catch { EventLogs.WriteFailedLog("Failed ScheduledEventCallBack"); } }
具EventManager.Execute()中的任务可以自由配置,你可以研究一下Discuz的这个模块
Discuz.Forum.ScheduledEvents
我上传一段吧
using System; using System.Diagnostics; using System.Web; using System.Threading; using Discuz.Config; using Discuz.Common.Generic; using Discuz.Common; namespace Discuz.Forum.ScheduledEvents { /// <summary> /// EventManager is called from the EventHttpModule (or another means of scheduling a Timer). Its sole purpose /// is to iterate over an array of Events and deterimine of the Event's IEvent should be processed. All events are /// added to the managed threadpool. /// </summary> public class EventManager { public static string RootPath; private EventManager() { } public static readonly int TimerMinutesInterval = 5; static EventManager() { if (ScheduleConfigs.GetConfig().TimerMinutesInterval > 0) { TimerMinutesInterval = ScheduleConfigs.GetConfig().TimerMinutesInterval; } } public static void Execute() { Discuz.Config.Event[] simpleItems = ScheduleConfigs.GetConfig().Events; Event[] items; #if NET1 ArrayList list = new ArrayList(); #else List<Event> list = new List<Event>(); #endif foreach (Discuz.Config.Event newEvent in simpleItems) { if (!newEvent.Enabled) { continue; } Event e = new Event(); e.Key = newEvent.Key; e.Minutes = newEvent.Minutes; e.ScheduleType = newEvent.ScheduleType; e.TimeOfDay = newEvent.TimeOfDay; list.Add(e); } #if NET1 items = (Event[])list.ToArray(typeof(Event)); #else items = list.ToArray(); #endif Event item = null; if(items != null) { for(int i = 0; i<items.Length; i++) { item = items[i]; if(item.ShouldExecute) { item.UpdateTime(); IEvent e = item.IEventInstance; ManagedThreadPool.QueueUserWorkItem(new WaitCallback(e.Execute)); } } } } } }
这是单个任务,我需要的是多个任务同时进行,而且配置的定时时间都是直接从数据库中读取的,不同的产品不同的定时时间,都是可变的
@ganzhushangjia: 你确定看过它的源码吗?
Quatz
Quatz.Net,这个比较好用,强烈推荐。