Fork me on GitHub
CJCMS系列---说说项目中的任务管理模式

 在系统开发过程中,肯定会有许多比较大型的任务需要去做,例如给所有注册的用户发送推广邮件,可是要是注册用户达到几十万级别,那我想这个发送邮件的工作可能真的让你很头疼,几十万的发送量,根本无法保证发送过程不会出错,被应用程序池回收,毕竟占得内存太大了,或者耗时过长。那任务管理不得不提上来讲讲了。

  任务管理,最重要的就是保证任务能够完整的完成,不管遇到什么问题,是否线程崩溃或被回收。

  就拿你要发邮件做例子,这么多的邮件,我想不可能一次就发完的,那我们就隔几分钟发送1000人也好啊。

  下面是代码:

  

复制代码
 1 /******************************************************************
 2 * 作者:                    不要理我 CJ
 3 * 邮件:               869722304@qq.com(仅仅支持商业合作洽谈)
 4 * 创建时间:                2012-8-16 20:12:38
 5 * 最后修改时间:            2012-8-16 20:12:38
 6 * 
 7 * 未经修改的文件版权属于原作者所有,但是你可以阅读,修改,调试。本项目不建议商用,不能确保稳定性。
 8 * 同时由于项目bug引起的一切问题,原作者概不负责。
 9 *
10 * 本项目所引用的所有类库,仍然遵循其原本的协议,不得侵害其版权。
11 *
12 * 您一旦下载就视为您已经阅读此声明。
13 *
14 * 您不可以移除项目中的任何声明。
15 *******************************************************************/
16 using System;
17 using System.Collections.Generic;
18 using System.Linq;
19 using System.Text;
20 
21 namespace CJCMS.Framework.Task
22 {
23     public interface IBackgroundTask
24     {
25         bool IsWorking { get; set; }
26         void DoWork();
27     }
28 }
复制代码

 

复制代码
 1 /******************************************************************
 2 * 作者:                    不要理我 CJ
 3 * 邮件:               869722304@qq.com(仅仅支持商业合作洽谈)
 4 * 创建时间:                2012-8-16 21:17:01
 5 * 最后修改时间:            2012-8-16 21:17:01
 6 * 
 7 * 未经修改的文件版权属于原作者所有,但是你可以阅读,修改,调试。本项目不建议商用,不能确保稳定性。
 8 * 同时由于项目bug引起的一切问题,原作者概不负责。
 9 *
10 * 本项目所引用的所有类库,仍然遵循其原本的协议,不得侵害其版权。
11 *
12 * 您一旦下载就视为您已经阅读此声明。
13 *
14 * 您不可以移除项目中的任何声明。
15 *******************************************************************/
16 
17 using System;
18 using System.Collections.Generic;
19 using System.Linq;
20 using System.Text;
21 
22 namespace CJCMS.Framework.Task
23 {
24     public class DefaultBackgroundTask:IBackgroundTask
25     {
26         public bool IsWorking { get; set; }
27 
28         public DefaultBackgroundTask()
29         {
30             IsWorking = true;
31         }
32 
33         public int k = 0;
34         public void DoWork()
35         {
36             k += 1;//当然这里实现发邮件也是可以的。
37         }
38     }
39 }
复制代码
复制代码
 1 /******************************************************************
 2 * 作者:                    不要理我 CJ
 3 * 邮件:               869722304@qq.com(仅仅支持商业合作洽谈)
 4 * 创建时间:                2012-8-16 20:14:04
 5 * 最后修改时间:            2012-8-16 20:14:04
 6 * 
 7 * 未经修改的文件版权属于原作者所有,但是你可以阅读,修改,调试。本项目不建议商用,不能确保稳定性。
 8 * 同时由于项目bug引起的一切问题,原作者概不负责。
 9 *
10 * 本项目所引用的所有类库,仍然遵循其原本的协议,不得侵害其版权。
11 *
12 * 您一旦下载就视为您已经阅读此声明。
13 *
14 * 您不可以移除项目中的任何声明。
15 *******************************************************************/
16 using System;
17 using System.Collections.Generic;
18 using System.Linq;
19 using System.Text;
20 using System.Timers;
21 
22 namespace CJCMS.Framework.Task
23 {
24     public interface IBackgroundTaskManager
25     {
26         Timer _timer { get; set; }
27         void Elapsed(object sender, ElapsedEventArgs e);
28     }
29 }
复制代码
复制代码
  1 /******************************************************************
  2 * 作者:                    不要理我 CJ
  3 * 邮件:               869722304@qq.com(仅仅支持商业合作洽谈)
  4 * 创建时间:                2012-8-16 20:52:35
  5 * 最后修改时间:            2012-8-16 20:52:35
  6 * 
  7 * 未经修改的文件版权属于原作者所有,但是你可以阅读,修改,调试。本项目不建议商用,不能确保稳定性。
  8 * 同时由于项目bug引起的一切问题,原作者概不负责。
  9 *
 10 * 本项目所引用的所有类库,仍然遵循其原本的协议,不得侵害其版权。
 11 *
 12 * 您一旦下载就视为您已经阅读此声明。
 13 *
 14 * 您不可以移除项目中的任何声明。
 15 *******************************************************************/
 16 
 17 using System;
 18 using System.Collections.Generic;
 19 using System.Linq;
 20 using System.Text;
 21 using System.Timers;
 22 
 23 namespace CJCMS.Framework.Task
 24 {
 25     public class DefaultBackgroundTaskManager:IBackgroundTaskManager
 26     {
 27         public Timer _timer { get; set; }
 28         private static Dictionary<string, IBackgroundTask> _entries = new Dictionary<string, IBackgroundTask>();
 29 
 30         public TimeSpan Interval
 31         {
 32             get { return TimeSpan.FromMilliseconds(_timer.Interval); }
 33             set { _timer.Interval = value.TotalMilliseconds; }
 34         }
 35 
 36         public DefaultBackgroundTaskManager(double min)
 37         {
 38             _timer = new Timer();
 39             Interval = TimeSpan.FromMinutes(min);
 40             _timer.Elapsed += Elapsed;
 41             _timer.Start();
 42         }
 43 
 44         public void Elapsed(object sender, ElapsedEventArgs e)
 45         {
 46             if (!System.Threading.Monitor.TryEnter(_timer))
 47                 return;
 48 
 49             try
 50             {
 51                 if (_timer.Enabled)
 52                 {
 53                     foreach (KeyValuePair<string, IBackgroundTask> k in _entries.ToList())
 54                     {
 55                         if (k.Value.IsWorking)
 56                         {
 57                             k.Value.DoWork();
 58                         }
 59                         else
 60                         {
 61                             Remove(k.Key);
 62                         }
 63                     }
 64                 }
 65             }
 66             catch (Exception ex)
 67             {
 68                
 69             }
 70             finally
 71             {
 72                 System.Threading.Monitor.Exit(_timer);
 73             }
 74             
 75         }
 76 
 77         ~DefaultBackgroundTaskManager()
 78         {
 79             _timer.Stop();
 80         }
 81 
 82         private static void Add(string key, IBackgroundTask task)
 83         {
 84             lock (_entries)
 85             {
 86                 _entries.Add(key, task);
 87             }
 88         }
 89 
 90         public static void Remove(string key)
 91         {
 92             lock (_entries)
 93             {
 94                 _entries.Remove(key);
 95             }
 96         }
 97 
 98         public static void TryAdd(string key, IBackgroundTask task)
 99         {
100             if (_entries.Where(a => a.Key == key).Count() == 0)
101             {
102                 Add(key, task);
103             }
104         }
105     }
106 }
复制代码

  你看到了,任务管理其实是用了Timer来实现,我设计一个定时器,隔几分钟就执行以下任务,不管成功不成功,都得执行。

  但是你得注意,这个执行是重新执行的意思,所以假若你想实现发送邮件,放置一直重复发送,你可以用一张表记录发送到哪里了,放置一直在发送。任务没有实现记录任务状态,后面也许我会改进改进,让这个任务管理记住状态,但是我觉得很难抽象出所有的任务类型。

  

 
 

前面写了比较多的基础知识,简单来说就是项目的帮助类库吧,下面我就开始写现在比较火的电子商务作为实践的例子,让大家对于我这个架构的赤裸裸的理解,共同进步。

  首先,都是前言了。

  这次电子商务项目实战呢,我个人对于自己前端的水平真的是不自信,因为只会抄抄别人的东西。所以我大部分的内容都会讲如何通过DDD的思想来构建这样一个系统出来,前端的效果,要是大家有什么比较好用的现成的架构可以推荐给我,同时在开发过程中,我有可能会对之前的项目结构进行重构,毕竟能力有限,请大家批评指正。

  先大体上分析一下,电子商务的一些主要的需求。电子商务主要就是商品,商品属性,购物车,订单,订单状态切换,收货地址,用户。

  下面是一张我从网络上搜索过来的电子商务的功能结构图,可以说这张图功能真的够了。这里是原文链接

      电子商务功能结构图

 

  上面真的把基本上的功能都涵盖了,看到这张图,我觉得我后面的工作还有很多。好了,今天就说这些了。

posted on 2012-08-19 22:21  HackerVirus  阅读(268)  评论(0编辑  收藏  举报