一种异步作业处理请求任务的简单实现(以短信发送为例)

对于以下几类任务,可能需要异步处理,即不是在接口中处理任务,而是在另一个调用作业中处理:

  1. 处理比较耗时、耗时CPU、内存资源
  2. 不很稳定、可能失败但又比较重要,若失败需要多尝试几次
  3. 请求量大、性能要求高。若放在接口中处理不方便拓展机器、负载等

主要程序流程图如下:

 

下面说下程序主要框架:

1.框架         

1.Interface 短信发送请求接口,通过json类对象调用。只接受保存任务,状态-未处理。稍后异步在job里处理
2.Job 异步的后端短信发送程序,一个个处理未发送的消息,含2个互备供应商,可切换
3.Web 后台,查看任务处理情况、账号等
4.Interface.Entity 接口模型实体,请求、响应类对象
5.Test 接口请求测试项目,通过Entity的json序列化、http post参数形式请求Interface
6.Model DB模型,含底层EF操作类库
7.Service 主要业务逻辑封装
8.Repository 主要DB对象封装

2.接口

 1 public class InterfaceController : Controller
 2     {
 3         public void Index()
 4         {
 5             Response.Write("欢迎访问消息发送接口");
 6         }
 7 
 8         [HttpPost]
 9         public JsonResult Send()
10         {
11             MessageResponseEntity response;
12             try
13             {
14                 string jsonRequest = GetPostData();
15                 if (jsonRequest.IsNullOrWhiteSpace())
16                 {
17                     response = new MessageResponseEntity
18                     {
19                         TaskId = string.Empty,
20                         SendStatus = SendStatus.SendFailure,
21                         ResultDescription = "所有请求参数为空",
22                     };
23                 }
24                 else
25                 {
26                     MessageRequestEntity request = JsonConvert.DeserializeObject<MessageRequestEntity>(jsonRequest);
27                     var service = new SendService();
28                     response = service.Verify(request);
29                     if (response.SendStatus != SendStatus.SendFailure)
30                         response = service.SaveMessage(request);
31                 }
32             }
33             catch (Exception ex)
34             {
35                 response = new MessageResponseEntity
36                 {
37                     TaskId = string.Empty,
38                     SendStatus = SendStatus.SendFailure,
39                     ResultDescription = string.Format("服务器端出错,原因:{0},{1}",ex.Message,ex.StackTrace),
40                 };
41             }
42             return Json(response);
43         }
44 
45         public string GetPostData()
46         {
47             string postData = string.Empty;
48             if (Request.RequestType == "POST")
49             {
50                 using (Stream sm = Request.InputStream)
51                 {
52                     int len = (int)sm.Length;
53                     byte[] inputByts = new byte[len];
54                     sm.Read(inputByts, 0, len);
55                     postData = Server.UrlDecode(Encoding.GetEncoding(Encoding.UTF8.WebName).GetString(inputByts));
56                 }
57             }
58             return postData;
59         }
60     }
View Code

3.调用方法:

1             //调用测试
2             var request = new MessageRequestEntity
3             {
4                 Content = "测试",
5                 Receivers = "15951984463",
6                 AccountGuid = "a8bfdd46-e7f6-4ad6-9fc6-ce69a9eb2633",
7             };
8             var response = CommTools.WebUtils.Post<MessageResponseEntity>("http://localhost:1952/Interface/send", request);
9             Response.Write(string.Join(",", response.TaskId, response.SendStatus, response.ResultDescription));      

4.处理作业

 1 public class HomeController : Controller
 2     {
 3         public static JobStatus JobStatus; 
 4 
 5         public ActionResult Index()
 6         {
 7             ViewBag.Message = "欢迎访问发送信息Job!  当前Job运行状态:" + JobStatus.ToString();
 8             return View();
 9         }
10 
11         public void StartJob()
12         {
13             Response.Write("发送信息Job已启动");
14             JobStatus = JobStatus.Running;
15             var taskOperation = new TaskOperation();
16             while (true)
17             {
18                 taskOperation.SingleSendMessage();
19                 Thread.Sleep(100);  //暂停100毫秒,即100毫秒处理一个消息发送任务
20             }
21         }
22     }
View Code
 1 public void SingleSendMessage()
 2         {
 3             var taskRepos = new TaskRepository();
 4             Task waitSendTask = taskRepos.GetTopWaitSendTask();
 5             if (waitSendTask != null)
 6             {
 7                 bool supplierResult;
 8                 int supplierId;
 9                 //指定模式:0-先提交供应商A,再提交B;1-只提交供应商A,对应A Id;2-只提交供应商B,对应B Id。
10                 int supplierMode = int.Parse(ConfigurationManager.AppSettings["SupplierMode"]);
11                 switch (supplierMode)
12                 {
13                     case 0: 
14                         {
15                             supplierId = 1;
16                             supplierResult = new SupplierA().SendMessage(waitSendTask);
17                             if (!supplierResult)    //提交供应商A失败则提交供应商B
18                             {
19                                 supplierId = 3;
20                                 supplierResult = new SupplierB().SendMessage(waitSendTask);
21                             }
22                             break;
23                         }
24                     case 1:
25                         {
26                             supplierId = 1;
27                             supplierResult = new SupplierA().SendMessage(waitSendTask);
28                             break;
29                         }
30                     case 3:
31                         {
32                             supplierId = 3;
33                             supplierResult = new SupplierB().SendMessage(waitSendTask);
34                             break;
35                         }
36                     default:
37                         {
38                             supplierId = 1;
39                             supplierResult = new SupplierA().SendMessage(waitSendTask);
40                             break;
41                         }
42                 }
43 
44                 if(supplierResult)
45                     taskRepos.TaskSendStatus(waitSendTask.TaskId, SendStatus.SendSuccess, "发送成功",supplierId);
46                 else
47                     taskRepos.TaskSendStatus(waitSendTask.TaskId, SendStatus.SendFailure, "发送失败:提交供应商失败", supplierId);
48             }
49         }
View Code

 

具体代码,我打包提交上来或者git上传,供各位参考

 

posted on 2015-10-08 22:32  nlh774  阅读(669)  评论(0编辑  收藏  举报