需求: 针对 淘宝提出的 订单全链路 产品接入 .http://open.taobao.com/doc/detail.htm?id=102423&qq-pf-to=pcqq.group

oms(订单管理系统) 实现  , 完毕后 效果:在千牛工作台 --订单全链路  可看到效果例如以下图

 

-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

目标: client 使用消息队列 将订单信息保存, 服务端使用  Windows服务 ,将消息队列中的订单信息 通过淘宝api 上传到淘宝.

---(截图上传了 4次 才看到效果 ,最后从简  见谅)

一、创建一个Windows Service

1)创建Windows Service项目

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvc2FnZTQyNQ==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="">

2)对Service重命名

将Service1重命名为你服务名称。这里我们命名为TradeTraceService。

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvc2FnZTQyNQ==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="">

二、创建服务安装程序

1)加入安装程序

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvc2FnZTQyNQ==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="">

之后我们能够看到上图,自己主动为我们创建了ProjectInstaller.cs以及2个安装的组件。

2)改动安装服务名

右键serviceInsraller1。选择属性。将ServiceName的值改为TradeTraceService。

  • 补充:

1.Service启动属性:

Manual      服务安装后。必须手动启动。

Automatic    每次计算机又一次启动时,服务都会自己主动启动。

Disabled     服务无法启动。

3)改动安装权限

右键serviceProcessInsraller1。选择属性,将Account的值改为LocalSystem。

三、创建 类库 封装方法(用于:将消息队列中数据 通过淘宝api上传到淘宝 ),写入服务代码

1)
创建类库

2)
创建接口 和相应实现

3)
代码展示

ITradeTraceService.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.ServiceModel;
using System.Text; namespace TradeTrace.Service
{
[ServiceContract]
public interface ITradeTraceService
{
/// <summary>
/// 把订单信息插入到队列里
/// </summary>
/// <param name="orderSource"></param>
/// <param name="orderNum"></param>
/// <param name="status"></param>
/// <param name="createtime"></param>
[OperationContract(IsOneWay = true)]
void Insert(int orderSource, string orderNum, int status, DateTime createtime );
}
}

TradeTraceService.cs

using ECERP.FrameWork.Log;
using System;
using System.Collections.Generic;
using System.Linq;
using System.ServiceModel;
using System.Text; namespace TradeTrace.Service
{
[ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Single)]
public class TradeTraceService : ITradeTraceService
{
public void Insert(int orderSource, string orderNum, int status, DateTime createtime)
{
Logger.Info(string.Format("[淘宝订单 全链路]读取店铺:{0},订单:{1},状态:{2}", orderSource, orderNum, status));
DateTime dt = DateTime.Now;
if (string.IsNullOrEmpty(orderNum) || orderNum == "0" ||orderSource==0)
{
Logger.Info(string.Format("[淘宝订单 全链路]公布消息 时读取到 异常单号:{0},店铺:{1},时间:{2}", orderNum, orderSource, dt));
return;
}
try
{
var list = ECERP.AddIn.ShopService.ShopList;
var shop = list.FirstOrDefault(c => c.ID == orderSource);
//var shop = ECERP.Service.ShopService.Instance.GetShopByID(orderSource);
if (shop != null)
{
ECERP.AddIn.TaoBao.Service.TradeTraceService trace = new ECERP.AddIn.TaoBao.Service.TradeTraceService(shop);
trace.TradeTraceMessageProduce(orderNum, status, createtime); Logger.Info("OrderNum:" + orderNum + " createtime:" + createtime + " OrderSource:" + orderSource + "耗时:" + (DateTime.Now - dt));
}
else
{
Logger.Info("shop is null" + orderSource);
}
}
catch (Exception ex)
{
Logger.Error("淘宝订单 全链路 (正向交易状态跟踪消息) 异常", ex);
}
}
}
}

4)
写入服务代码:打开TradeTraceService代码

右键TradeTraceService.cs,选择查看代码。

TradeTraceService.cs

using ECERP.FrameWork.Log;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Linq;
using System.Messaging;
using System.ServiceModel;
using System.ServiceProcess;
using System.Text; namespace TradeTrace.Host
{
public partial class TradeTraceService : ServiceBase
{
ServiceHost host = new ServiceHost(typeof(TradeTrace.Service.TradeTraceService));
public TradeTraceService()
{
InitializeComponent();
} protected override void OnStart(string[] args)
{
if (!MessageQueue.Exists(@".\private$\tradetracelist"))
{
Logger.Info("不存在队列创建");
var mq = MessageQueue.Create(@".\private$\tradetracelist", true);
//能够依据实际情况自己设置
mq.SetPermissions("Everyone", MessageQueueAccessRights.FullControl);
}
else
{
Logger.Info("已经存在队列");
}
try
{
host.Open();
Logger.Info("服务開始启动了");
}
catch (Exception ex)
{
Logger.Error("err", ex);
}
} protected override void OnStop()
{
try
{
host.Close();
Logger.Info("服务关闭了");
}
catch (Exception ex)
{
host.Abort();
Logger.Error("err",ex);
}
}
}
}

应用程序入口  Program.cs

using ECERP.FrameWork.Log;
using System;
using System.Collections.Generic;
using System.Configuration.Install;
using System.Linq;
using System.ServiceProcess;
using System.Text; namespace TradeTrace.Host
{
static class Program
{
/// <summary>
/// 应用程序的主入口点。
/// </summary>
static void Main(string[] args)
{
string f = AppDomain.CurrentDomain.BaseDirectory + "Log.config";
log4net.Config.XmlConfigurator.ConfigureAndWatch(new System.IO.FileInfo(f)); Logger.Info("start..."); try
{
// 执行服务
if (args.Length == 0)
{
try
{
ServiceBase[] ServicesToRun = new ServiceBase[] { new TradeTraceService() };
ServiceBase.Run(ServicesToRun);
}
catch (Exception ex)
{
Logger.Error("err", ex);
}
}
// 安装服务
else if (args[0].ToLower() == "/i" || args[0].ToLower() == "-i")
{
try
{
string[] cmdline = { };
string serviceFileName = System.Reflection.Assembly.GetExecutingAssembly().Location; TransactedInstaller transactedInstaller = new TransactedInstaller();
AssemblyInstaller assemblyInstaller = new AssemblyInstaller(serviceFileName, cmdline);
transactedInstaller.Installers.Add(assemblyInstaller);
transactedInstaller.Install(new System.Collections.Hashtable());
}
catch (Exception ex)
{
Logger.Error("err", ex);
//string msg = ex.Message;
}
}
// 删除服务
else if (args[0].ToLower() == "/u" || args[0].ToLower() == "-u")
{
try
{
string[] cmdline = { };
string serviceFileName = System.Reflection.Assembly.GetExecutingAssembly().Location; TransactedInstaller transactedInstaller = new TransactedInstaller();
AssemblyInstaller assemblyInstaller = new AssemblyInstaller(serviceFileName, cmdline);
transactedInstaller.Installers.Add(assemblyInstaller);
transactedInstaller.Uninstall(null);
}
catch (Exception ex)
{
Logger.Error("err", ex);
}
}
}
catch (Exception ex)
{
Logger.Error("err", ex);
} }
}
}

5) log.config 日志文件 和app.config 数据库配置 文件

log.config
 基本 没啥大变化  不做展示

app.config

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<connectionStrings>
<add name="local" connectionString="server=.;database=txttt0808;uid=sa;Pwd=" providerName="sql2005"/>
</connectionStrings> <system.serviceModel>
<services>
<service name="TradeTrace.Service.TradeTraceService">
<endpoint address="net.msmq://localhost/private/tradetracelist" binding="netMsmqBinding"
bindingConfiguration="msmq" contract="TradeTrace.Service.ITradeTraceService" />
</service>
</services> <bindings>
<netMsmqBinding>
<binding name="msmq" exactlyOnce="true">
<security mode="None" />
</binding>
</netMsmqBinding>
</bindings> </system.serviceModel>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/>
</startup>
</configuration>

需注意的 是 消息队列 服务地址配置

6) 项目总体 展示

四、安装 服务

用.net framework工具INSTALLUTIL安装服务程序就可以。

用项目的输出作为參数。从命令行执行 InstallUtil.exe。在命令行中输入下列代码:

installutil yourproject.exe

五、卸载 服务

用项目的输出作为參数,从命令行执行 InstallUtil.exe。

installutil
/u yourproject.exe

六
. client 代码

公共方法 : 在你任务 须要的 地方 自己调用

  /// <summary>
/// 把订单信息保存到msmq里
/// </summary>
/// <param name="list"></param>
private void SaveTradeTraceToMsmq(List<SalesOrder> list)
{
ChannelFactory<TradeTrace.Service.ITradeTraceService> channelFactory = new ChannelFactory<TradeTrace.Service.ITradeTraceService>("TradeTraceServiceClient");
TradeTrace.Service.ITradeTraceService calculate = channelFactory.CreateChannel();
int i = 0;
DateTime beginTime = DateTime.Now;
foreach (var order in list)
{
calculate.Insert(order.OrderSource.GetValueOrDefault(0), order.OrderNum, order.Status.GetValueOrDefault(0),DateTime.Now);
Logger.Info(string.Format("orderNum:{0} createtime:{1} shop:{2} no:{3}", order.OrderNum, order.ModifyTime, shop.Name, ++i));
} Logger.Info(string.Format("{0}保存进队列{1}/{2}条 time:{3} 耗时:{4}", shop.Name, i, list.Count, DateTime.Now, DateTime.Now.Subtract(beginTime)));
}

client配置文件 截图

总结:
 Windows服务 和消息队列的 结合使用 会让你的 程序 焕然一新,更加灵活 . 消息队列的 相关知识 请自寻资料了解.

小小心得
不正确的地方 请多多不吝赐教 .

C#编写Windows服务程序 (服务端),client使用 消息队列 实现淘宝 订单全链路效果的更多相关文章

  1. C语言编写Windows服务程序

    原文:C语言编写Windows服务程序 #include <Windows.h> #include <stdio.h> #define SLEEP_TIME 5000 // 间 ...

  2. (8)Linux(客户端)和Windows(服务端)下socket通信实例

    Linux(客户端)和Windows(服务端)下socket通信实例: (1)首先是Windows做客户端,Linux做服务端的程序 Windows   Client端 #include <st ...

  3. 编写windows服务程序

    2012-11-02 08:54 (分类:计算机程序) windows服务是一个运行在后台并实现勿需用户交互的任务的控制台程序,对于隐藏程序有很大帮助. 用了几天时间概括了编写windows服务程序的 ...

  4. ftpget 从Windows FTP服务端获取文件

    /********************************************************************************* * ftpget 从Windows ...

  5. 书剑恩仇录online全套源代码(服务端+client+文档)

    书剑恩仇录online全套源代码(服务端+client+文档).vc++开发,解压后将近10G大小,眼下网上最完整版本号,包括client源代码.服务端源代码.工具源代码.sdk.文档-- <书 ...

  6. Akka(43): Http:SSE-Server Sent Event - 服务端主推消息

    因为我了解Akka-http的主要目的不是为了有关Web-Server的编程,而是想实现一套系统集成的api,所以也需要考虑由服务端主动向客户端发送指令的应用场景.比如一个零售店管理平台的服务端在完成 ...

  7. java Socket通信,客户端与服务端相互发消息

    1.通信过程 网络分为应用层,http.ssh.telnet就是属于这一类,建立在传输层的基础上.其实就是定义了各自的编码解码格式,分层如下: 2.Socket连接 上述通信都要先在传输层有建立连接的 ...

  8. Spring Boot 集成 WebSocket 实现服务端推送消息到客户端

    假设有这样一个场景:服务端的资源经常在更新,客户端需要尽量及时地了解到这些更新发生后展示给用户,如果是 HTTP 1.1,通常会开启 ajax 请求询问服务端是否有更新,通过定时器反复轮询服务端响应的 ...

  9. netty-2.客户端与服务端互发消息

    (原) 第二篇,客户端与服务端互发消息 与第一篇的例子类似,这里服务端需要三个类,客户端也需要三个类. 服务端关键代码如下:MyServer与上一个例子中的TestServer 差多,这里只列举不同的 ...

随机推荐

  1. java中迭代器应用

    本文将利用分析代码的方式,来学习一个集合类的内部结构,以及遍历集合的迭代模式的源码实现细节. 下面我们先简单讨论一个根接口Collection,然后分析一个抽象类AbstractList和它的对应It ...

  2. Nginx和Tomcat负载均衡实现session共享

    以前的项目使用Nginx作为反向代理实现了多个Tomcat的负载均衡,为了实现多个Tomcat之间的session共享,使用了开源的Memcached-Session-Manager框架. 此框架的优 ...

  3. Java发邮件带附件测试通过

    package cn.bric.crm.util; import java.util.Date; import java.util.Enumeration; import java.util.Prop ...

  4. 【BZOJ】【2200】【USACO 2011 Jan】道路和航线

    做了一天…… TLE:数组开小了-_-#道路是有50000的,双向要乘二.(我特么怎么想的就以为是树了……) WA:一些大点都WA了,小点都过了.好纠结…… AC了QAQ,不知道为什么,在并查集合并的 ...

  5. 【BZOJ】【1968】【AHOI2005】COMMON 约数研究

    数论 原谅我这么傻逼的题都不会做…… 或许写成数学公式的形式比较容易想到解法? $$ans=\sum_{i=1}^n \sum_{d|i} 1$$ ……是不是感觉很水呀……是吧……改成先枚举d再枚举 ...

  6. SVN使用小结

    SVN是Subversion的简称.是一个开放源码的版本号控制系统.在它的管理下,文件和文件夹能够超越时空的限制,权且当作一种奇妙的"时间机器"吧. 基本功能 版本号控制 作为一个 ...

  7. @JVM中的几种垃圾收集算法

    标记-清除(Mark-Sweep) 算法分为"标记"和"清除"两个阶段:首先标记出所有需要回收的对象,在标记完成后统一回收掉所有被标记的对象(没有与GC Roo ...

  8. pymysql的使用心得(1)------小细节,注意!

    最近一段时间开始使用MySQL,使用的是pymysql库. 其中遇到过一些小问题,值得记录一下,以便今后使用的时候注意到. 表格的建立,代码如下: cursor.execute("creat ...

  9. java 判断字符串是否相等 (转)

    http://blog.csdn.net/chtnj/article/details/7909720 判断字符串相等我们经常习惯性的写上if(str1==str2),这种写法在java中可能会带来问题 ...

  10. (转)UnityVS(Visual Studio Tools For Unity)的安装与使用

    UnityVS(Visual Studio Tools For Unity)的安装与使用   一些废话 Unity 的开发者们,尤其是微软系的Unity开发者们,用Mono是不是烦死了?你是不是跟我一 ...