上文详细讨论了MQ的使用方法,MQ作为一种信息存储机制,将消息存储到了队列中,这样在做分布式架构时可以考虑将消息传送到MQ服务器上,然后开发相应的服务组件获取MQ中的消息,自动获取传送的消息,将消息发送给处理的程序。那么上文就MQ做了详细的讨论,并没有介绍有关服务组件的内容,也就是说如果我们开发的程序想要实现自动的消息接收和推送的服务的话,这里就必须考虑使用Windows Service来实现了,Windows Service是一种实时运行的组件,可以实时处理消息,该篇文章将会讨论Windows Service的开发方法。

一、WS理论篇

MQ和WS技术相结合其实就可以看做是一个简单的ESB程序,这样可以通过调用服务来实现消息中间件的处理功能,可以开发包括消息推送、接收、处理的应用程序。WS是在Windows操作系统中才会有的,是集成到系统中的,一个WS在开启后会一直运行,直到停止该WS。在具体的项目中开发的WS是作为组件存在的,也就是说系统中的某部分需要实时运行,这时候可以考虑开发WS组件。

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配置服务本身属性,如服务名称、服务启动方法等。


二、WS Demo

上文对WS的基本内容做了详细的了解,通过理论来指导实践,这样在开发的时候思路才能够很清晰,关于WS的理论部分这里不再详细的讨论,接下来我们开发一个简单的WS Demo。
       上篇文章详细讨论了MQ的开发方法,并开发了一个简单的MQ项目,这里就继续使用上文的MQ的项目来开发一个对MQ消息处理的WS组件,该组件主要是负责处理消息队列中的信息,获取消息,并把消息的主题内容保存到文本中。
       具体程序的分布图如下所示:
                                        

2.1 服务代码

上面的程序分布图是结合上文的MQ来绘制的详细的架构图,其中的数据发送部分的程序在上文已经有介绍,这里不再详细讨论,下面的代码就是演示了分布图中的Service Handle data和Save data部分的功能,具体功能如下代码:

  1. using System;
  2. using System.IO;
  3. using System.ServiceProcess;
  4. using System.Threading;
  5. using System.Timers;
  6. using System.Messaging;
  7. namespace WindowsService1
  8. {
  9. public partial class Service1 : ServiceBase
  10. {
  11. //declare a MQ
  12. private MessageQueue queue;
  13. public Service1()
  14. {
  15. InitializeComponent();
  16. //create a path for queue
  17. string strpath = ".\\Private$\\EKTestQueue";
  18. //create a messagequeue and assign a path for this queue
  19. queue= new MessageQueue(strpath);
  20. //the queue formatter that can get queuebody based on the formatter
  21. queue.Formatter = new XmlMessageFormatter(new Type[] { typeof(string) });
  22. }
  23. /// <summary>
  24. /// service start event
  25. /// when we start this service then it will run this method
  26. /// </summary>
  27. /// <param name="args"></param>
  28. protected override void OnStart(string[] args)
  29. {
  30. //used to debug the code when start this service
  31. Thread.Sleep(30000);
  32. }
  33. /// <summary>
  34. /// service stop event
  35. /// </summary>
  36. protected override void OnStop()
  37. {
  38. }
  39. /// <summary>
  40. /// get message from queue and save the message to file
  41. /// </summary>
  42. private void GetAndWriteMessage()
  43. {
  44. //recevie a new one MQ
  45. var ms=queue.Receive();
  46. //save the data to file
  47. if (ms!=null)
  48. {
  49. this.AddTextLine(ms.Body.ToString());
  50. }
  51. }
  52. /// <summary>
  53. /// save the MQ message to file
  54. /// </summary>
  55. /// <param name="line">the message that want save</param>
  56. private void AddTextLine(string line)
  57. {
  58. try
  59. {
  60. //save the message to Message.txt file
  61. FileStream file=new FileStream("D:\\Message.txt",FileMode.OpenOrCreate,FileAccess.ReadWrite);
  62. StreamWriter writer=new StreamWriter(file);
  63. writer.BaseStream.Seek(0, SeekOrigin.End);
  64. writer.WriteLine(line+"\r\n");
  65. writer.Flush();
  66. writer.Close();
  67. file.Close();
  68. file.Dispose();
  69. }
  70. catch (Exception ex)
  71. {
  72. throw new Exception(ex.Message);
  73. }
  74. }
  75. private void timer1_Elapsed(object sender, ElapsedEventArgs e)
  76. {
  77. GetAndWriteMessage();
  78. }
  79. }
  80. }
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中才能够查看服务是否正常运行,因为服务不同于一般的应用程序,想要使用服务就必须将服务安装到系统当中。另外服务的调试也是很麻烦的一件事,因为服务不同于应用程序,想要调试它就不能采用普通的调试方法了,这里介绍一种附加进程的调试方法,还有其它如写日志等的调试方法,可以查看网上的文章来详细了解。

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 删除服务

在不使用服务后也可以删除服务,删除方法类似于服务的安装,具体方法如下所示:



     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。

版权声明:本文为博主原创文章,未经博主允许不得转载。

WebService 用法的更多相关文章

  1. JEECG(二) JEECG框架下调用webservice java springmvc maven 调用 webservice

    JEECG系列教程二 如何在JEECG框架下使用webservice 本文所使用的webservice是c#开发的 其实无论是什么语言开发的webservice用法都一样 java springmvc ...

  2. pb相关小技巧或用法

    1.动态post window lwlw = w_main lw.dynamic post event ue_all(ls_no,ls_table) 2.打开隐藏窗口 IF NOT IsValid(w ...

  3. Android webservice的用法详细讲解

    Android webservice的用法详细讲解 看到有很多朋友对WebService还不是很了解,在此就详细的讲讲WebService,争取说得明白吧.此文章采用的项目是我毕业设计的webserv ...

  4. ajax——client访问webservice基本用法

    学前aps.net当我学会了使用服务器端的访问webservice方法,然后实现一个样本:web server模拟网上购物,今天学习asp.net ajax的时候学习到了client直接訪问webse ...

  5. php无wsdl webservice服务用法

    服务端: <?php class test { function add($a,$b) { return $a+$b; } } function getUserInfo($name) { ret ...

  6. Jaxb的优点与用法(bean转xml的插件,简化webservice接口的开发工作量)

    一.jaxb是什么 JAXB是Java Architecture for XML Binding的缩写.可以将一个Java对象转变成为XML格式,反之亦然.     我们把对象与关系数据库之间的映射称 ...

  7. WebService基本使用

    不使用任何框架,纯粹使用JDK开发一个服务端与客户端 服务端 package org.zln.ws.server;import org.slf4j.Logger;import org.slf4j.Lo ...

  8. 性能测试总结工作总结-基于WebService协议脚本 内置函数手动编写

    LoadRunner基于WebService协议脚本 WebService协议脚本有三种生成方式,一种是直接通过LoadRunner导入URL自动解析生成:一种是使用LoadRunner内置函数手动编 ...

  9. 如何使用C#创建WebService

    使用C#创建WebService,服务端的webservice是必须,中间的soap,Xml我们不用去关心.下面是使用C#创建WebService的简单介绍. AD:51CTO技术沙龙 | 赋予APP ...

随机推荐

  1. PHPExcel 导出时乱码

    今天遇到了个奇怪的问题..猜测应该是因为php文件的编码造成的,但是没有解决办法. 问题是,用PHPEXCEL导出文件的时候,相同的代码在一个文件中可以导出,在另一个文件中却不行.. 最后没有办法,只 ...

  2. ayase系列

    [冒个泡]技能视觉效果の自定义 by ayase [11-09 V2.4]任务数量转换属性点的lua脚本 [335]瞎倒腾的item.dbc生成工具..

  3. 基于params,ref,out的参数问题详解

    http://www.jb51.net/article/37967.htm 最近在写程序时遇到params,ref,out 参数问题.回头有自习看了看MSDN,才巩固了基础.现在和大家分享一下.par ...

  4. Java--super关键字用法

    看了马老师的视频,百度了一下,随即敲了一些代码,super是超人,超级的意思,层面上理解为父类 class Person { Person(){             System.out.prin ...

  5. 分析案例:界面提示“基础链接已经关闭:接收时发生错误”----本质为StackOverflow

    问题描述: 一个业务复杂.执行时间很长的功能,经常报出“基础链接已经关闭:接收时发生错误”,很是蹊跷... 问题分析: 首先,查阅应用服务器的系统日志,发现问题发生时总是会伴随着w3wp进程崩溃的错误 ...

  6. [转]Windows 下的进程间通讯及数据共享

    http://blog.codingnow.com/2005/10/interprocess_communications.html Windows 下有很多方法实现进程间通讯,比如用 socket, ...

  7. Nginx快速入门菜鸟笔记

    Nginx快速入门-菜鸟笔记   1.编译安装nginx 编译安装nginx 必须先安装pcre库. (1)uname -a 确定环境 Linux localhost.localdomain 2.6. ...

  8. SQL 导出表结构到Excel

    SQL 导出表结构到Excel SELECT 表名 then d.name else '' end, 表说明 then isnull(f.value,'') else '' end, 字段序号 = a ...

  9. [zz] 海洋环境的光能传递

    source: http://cgangs.com/article/2557?source=weibo 就我们的目的来说,海洋环境仅由四部分组成:水表.空气.阳光和水表以下部分.在本节中,我们在数学和 ...

  10. HTML5常用的方法

    1.html禁止手机页面放大缩小 在页面head中加入<meta name="viewport" content="width=device-width, init ...