上文详细讨论了MQ的使用方法,MQ做为一种信息存储机制,将消息存储到了队列中,这样在作分布式架构时能够考虑将消息传送到MQ服务器上,而后开发相应的服务组件获取MQ中的消息,自动获取传送的消息,将消息发送给处理的程序。那么上文就MQ作了详细的讨论,并无介绍有关服务组件的内容,也就是说若是咱们开发的程序想要实现自动的消息接收和推送的服务的话,这里就必须考虑使用Windows Service来实现了,Windows Service是一种实时运行的组件,能够实时处理消息,该篇文章将会讨论Windows Service的开发方法。
1、WS理论篇
MQ和WS技术相结合其实就能够看作是一个简单的ESB程序,这样能够经过调用服务来实现消息中间件的处理功能,能够开发包括消息推送、接收、处理的应用程序。WS是在Windows操做系统中才会有的,是集成到系统中的,一个WS在开启后会一直运行,直到中止该WS。在具体的项目中开发的WS是做为组件存在的,也就是说系统中的某部分须要实时运行,这时候能够考虑开发WS组件。web
1.1 windows service VS web service
那么这里须要思考一个问题,windows Service和web Service它们两个都是服务,可是服务的对象是不一样的。在web应用程序中web service是一个行业的信息服务标准,它为web应用程序之间架设了一个桥梁,使得应用程序之间能够互相的交流通讯,也就是说web service是在web分布式应用中必然会用到的技术。
相较下来windows Service就比较狭窄了,它只能在windows system中运行,能够为windows的应用提供功能服务上的支持,在开发windows Service时经常会考虑两种状况,一是运行的组件考虑须要实时运行,另外是组件能够须要被多个程序调用,好比常常在开发中用到的sql server,它有不少子程序,这些程序之间会共用某个功能,因此此时就把它作成了一个服务。
1.2 ws开发
ws的组成是比较简单的,由于它自己固有的属性不多,大部分功能是经过调用其它的类库或者组件来组合功能,具体的ws的组成以下导图所示:
在开发ws时会有两个大的部分,分别是Service和Installer,Service是服务的内部功能逻辑,也就是服务的本体,服务要作的操做都是写到里面的;Installer是服务的安装部分,也就是配置了该服务在windows中显示的属性。
Service:继承自ServiceBase,其中包括服务全部的运行内容,开发界面相似于winForm中的自定义控件的开发,可以添加系统控件及第三方控件。
Installer:分为两种,其中的serviceProcessInstaller配置服务的被调用的用户类型,serviceInstaller配置服务自己属性,如服务名称、服务启动方法等。
2、WS Demo
上文对WS的基本内容作了详细的了解,经过理论来指导实践,这样在开发的时候思路才可以很清晰,关于WS的理论部分这里再也不详细的讨论,接下来咱们开发一个简单的WS Demo。
上篇文章详细讨论了MQ的开发方法,并开发了一个简单的MQ项目,这里就继续使用上文的MQ的项目来开发一个对MQ消息处理的WS组件,该组件主要是负责处理消息队列中的信息,获取消息,并把消息的主题内容保存到文本中。
具体程序的分布图以下所示:
2.1 服务代码
上面的程序分布图是结合上文的MQ来绘制的详细的架构图,其中的数据发送部分的程序在上文已经有介绍,这里再也不详细讨论,下面的代码就是演示了分布图中的Service Handle data和Save data部分的功能,具体功能以下代码:sql
- using System;
- using System.IO;
- using System.ServiceProcess;
- using System.Threading;
- using System.Timers;
- using System.Messaging;
-
-
- namespace WindowsService1
- {
- public partial class Service1 : ServiceBase
- {
-
- private MessageQueue queue;
- public Service1()
- {
- InitializeComponent();
-
-
- string strpath = ".\\Private$\\EKTestQueue";
-
- queue= new MessageQueue(strpath);
-
- queue.Formatter = new XmlMessageFormatter(new Type[] { typeof(string) });
- }
-
-
-
-
-
-
- protected override void OnStart(string[] args)
- {
-
- Thread.Sleep(30000);
- }
-
-
-
-
- protected override void OnStop()
- {
- }
-
-
-
- private void GetAndWriteMessage()
- {
-
- var ms=queue.Receive();
-
- if (ms!=null)
- {
- this.AddTextLine(ms.Body.ToString());
- }
- }
-
-
-
-
-
- private void AddTextLine(string line)
- {
- try
- {
-
- FileStream file=new FileStream("D:\\Message.txt",FileMode.OpenOrCreate,FileAccess.ReadWrite);
-
- StreamWriter writer=new StreamWriter(file);
- writer.BaseStream.Seek(0, SeekOrigin.End);
- writer.WriteLine(line+"\r\n");
- writer.Flush();
- writer.Close();
- file.Close();
- file.Dispose();
- }
- catch (Exception ex)
- {
- throw new Exception(ex.Message);
- }
- }
-
-
- private void timer1_Elapsed(object sender, ElapsedEventArgs e)
- {
- GetAndWriteMessage();
- }
- }
- }
using System;
using System.IO;
using System.ServiceProcess;
using System.Threading;
using System.Timers;
using System.Messaging;
namespace WindowsService1
{
public partial class Service1 : ServiceBase
{
//declare a MQ
private MessageQueue queue;
public Service1()
{
InitializeComponent();
//create a path for queue
string strpath = ".\\Private$\\EKTestQueue";
//create a messagequeue and assign a path for this queue
queue= new MessageQueue(strpath);
//the queue formatter that can get queuebody based on the formatter
queue.Formatter = new XmlMessageFormatter(new Type[] { typeof(string) });
}
/// <summary>
/// service start event
/// when we start this service then it will run this method
/// </summary>
/// <param name="args"></param>
protected override void OnStart(string[] args)
{
//used to debug the code when start this service
Thread.Sleep(30000);
}
/// <summary>
/// service stop event
/// </summary>
protected override void OnStop()
{
}
/// <summary>
/// get message from queue and save the message to file
/// </summary>
private void GetAndWriteMessage()
{
//recevie a new one MQ
var ms=queue.Receive();
//save the data to file
if (ms!=null)
{
this.AddTextLine(ms.Body.ToString());
}
}
/// <summary>
/// save the MQ message to file
/// </summary>
/// <param name="line">the message that want save</param>
private void AddTextLine(string line)
{
try
{
//save the message to Message.txt file
FileStream file=new FileStream("D:\\Message.txt",FileMode.OpenOrCreate,FileAccess.ReadWrite);
StreamWriter writer=new StreamWriter(file);
writer.BaseStream.Seek(0, SeekOrigin.End);
writer.WriteLine(line+"\r\n");
writer.Flush();
writer.Close();
file.Close();
file.Dispose();
}
catch (Exception ex)
{
throw new Exception(ex.Message);
}
}
private void timer1_Elapsed(object sender, ElapsedEventArgs e)
{
GetAndWriteMessage();
}
}
}
上面的代码主要是在服务中添加了信息处理的模块,这样就可以实现时时获取queue中的数据并对数据进行操做。
Note1:在服务的OnStart事件中添加了Thread.Sleep(3000)是为了调试服务启动代码而存在的,由于服务启动的时候是很快的也就是说咱们在调试代码时常常会将项目附加到服务中,可是这时候服务是已经启动的了,是没有办法调试它的,因此咱们添加了改行代码,这样就能够延迟服务的启动时间,给咱们制造了充足的时间将代码附加到服务中来调试服务的启动代码。
Note2:Timer控件,该控件必定要是System.Timers.Timer控件,由于在添加时可能会误添加为在Thread命名空间下载Timer控件,这样就会致使服务在启动时出错,不能正常注册该控件。
2.2 服务调试
在开发完成服务后不可以直接运行使用,而是要将服务安装到系统的Services中才可以查看服务是否正常运行,由于服务不一样于通常的应用程序,想要使用服务就必须将服务安装到系统当中。另外服务的调试也是很麻烦的一件事,由于服务不一样于应用程序,想要调试它就不能采用普通的调试方法了,这里介绍一种附加进程的调试方法,还有其它如写日志等的调试方法,能够查看网上的文章来详细了解。
windows
2.2.1 安装服务
首先要打开控制台并进入到C:/Windows/Microsoft.Net/Framework/v4.0.30319中,运行InstallUtil.exe工具,并添加相应的开发的服务程序,而后回车运行就能够安装,以下所示:服务器

C:/Windows/Microsoft.Net/Framework/v4.0.30319>InstallUtil.exe C:\Code\WindowsService1\WindowsService1\bin\Debug\WindowsService1.exe
安装完成后查看Services工具中的服务以下图所示:
架构
安装后服务显示的名称是根据ServiceInstaller的属性来控制的,在开发时指定了ServiceName属性名称为Jack's Service因此安装后显示的服务名称如上图所示。
2.2.2 将WS附加到进程
首先打开Tools下面的Attach to Process窗体,而后在程序中找到该服务,具体以下面两张图所示:
找到后双击该程序便可将添加源码到服务,这时候就可以对服务的代码进行调试了。
Note3:在附加进程时,所附加的进程名称是和服务的程序名称相一致的,并非和Services工具中的名称一致。由于该服务程序的名称为WindowsServices1因此咱们要把代码附加到该服务中,如上图所示。
2.2.3 删除服务
在不使用服务后也能够删除服务,删除方法相似于服务的安装,具体方法以下所示:app

C:/Windows/Microsoft.Net/Framework/v4.0.30319>InstallUtil.exe/u C:\Code\WindowsService1\WindowsService1\bin\Debug\WindowsService1.exe
分布式
结语
文章主要介绍了WS的基本构成,并经过一个具体的示例来演示开发WS时须要注意的地方,最后介绍了一种WS的调试方法,很简单,可是新手会有不少问题,具体的问题具体分析,能够留言讨论。
WS在分布式开发中拥有重要做用,它可以协调各个程序以前的交互功能,能够做为程序的通讯桥梁,可是WS自己有不少局限性,它只能运行在Windows系统中,另外WS的代码调试一直惨遭诟病,须要开发人员一次次的安装、附加进程、删除的操做,很耗费时间,因此在作分布式开发时必定要慎重考虑使用WS。
版权声明:本文为博主原创文章,未经博主容许不得转载。ide