寄宿WCF服务最常用的环境是IIS或者WAS。在一个公共架构上创建,它们都提供鲁棒性进程控制和生命周期回收服务,还有一个熟悉的管理接口。当IIS架构已经在使用时这是对大多数场景来说最合适的解决方案。
然而,也有一些情况你不想在IIS或者WAS中寄宿一个服务。你可能想显式控制事件的启动和停止。或者你可能想提供一个自定义管理接口而不是使用IIS或 者WAS工具。为了实现这个,你可以使用System.ServiceModel命名空间中的ServiceHost类来在任何程序中寄宿一个服务。当你 做这个时,你正在使用一个自我寄宿的WCF服务。
寄宿一个WCF服务最常用的场景是在一个随系统启动和停止的Windows托管服务中。一个Windows托管服务可能运行在支持WCF的一个操作系统 上,包括Windows XP, Windows 2003 Server, Windows Vista 或者Windows Server 2008. 这在这一章的”在一个Windows 托管服务中自我寄宿”中详细介绍。
另外一个寄宿服务的场景是在一个桌面应用程序中,使用WinForms(Win 窗体程序)或者WPF(Windows Presentation Framework,Windows 呈现架构)或者一个命令行控制台应用程序。服务可以使用对等网,使用一个广泛使用的地址以便于其他客户端可以给它发送消息,或者以一些其他方式来宣传它的 地址。如果服务使用一个一致的队列作为传输协议,消息可以发送给服务即便客户端没有在运行。一个一致的队列,由MSMQ实现或者是一个相关数据库的表,是 客户端和服务端实现通信的非常好的结构;客户端和服务端可能临时是彼此断开的。
实现一个自我寄宿服务是非常容易的。列表7.1列出了三个步骤。宿主,是创建ServiceHost对象并调用它的Open方法的程序,负责保持可用直到 需要关闭的时候。当创建ServiceHost时有一些选项,比如从哪里获取服务基地址和是否创建一个单例,但也就是如此。
第一章的列表1.1 和1.2 描述了一个自我寄宿的服务最少需求。这些列表显示了一个可以在一个服务的控制台或者在一个管理员的桌面运行的自我寄宿的控制台应用。
在一个Windows 托管服务中自我寄宿
Windows托管服务时可以由服务控制管理器(Service Control Manager, SCM)控制的操作系统进程。使用微软管理控制台服务(Microsoft Management Console, MMC)管理它们, 但是Windows 设备管理(Window Management Instrumentation, WMI)和SCM APIs 让它们对其他控制工具和脚本程序都可以使用。通过这些工具你可以控制很多特性,比如是否它们随操作系统自我启动以及它们运行时的Windows 身份。Windows 服务是一个企业应用比如Microsoft SQL Server 和Microsoft Exchange 的寄宿环境。
Windows 托管服务基础,可以在使用Win32 APIs的非托管代码和继承自System.ServiceProcess命名空间的ServiceBase类的托管代码中访问,提供了一个基本的管理接 口但是没有为你的代码做任何关于实际寄宿,扩展,安全和可信赖的工作。你负责完成所有的通信(MSMQ, 命名管道和TCP等等)和线程,实例以及控制流。幸运的是,这些特性在WCF中实现了,所有当你在一个Windows服务中寄宿一个WCF服务时,这些已 经为你做好了。
Visual Studio 有一个内建的定义Windows 服务的模板。当从这个模板创建一个工程时,基本有一个静态main() 负责启动你的服务以及一个你可以放你的代码的继承自ServiceBase的类。基本代码需要在两个步骤完成: 添加WCF ServiceHost类实例化你的服务并使用SCM注册服务。
首先,你需要添加代码到OnStart方法来开始处理接收到的消息。在引入WCF之前,这是你需要创建线程池,监听器和一个回收结构,所有的典型设置都不 能使用配置文件。但是通过使用WCF,所有你需要在OnStart方法中做的是创建ServiceHost并开启监听。使用EventLog来记录一条启 动消息也是有帮助的。
其次,你需要实现一个ProjectInstaller, 在System.Configuration.Install命名空间中定义和引用。ProjectInstaller类用来在目标机器安装托管服务。你 可以在一个安装程序中做这个或者你可以把它加入到服务本身。为了安装服务,接下来你需要使用installutil.exe实例来使用SCM注册服务。在 运行实例以后,服务已经准备通过SCM运行。
列表7.9显示了完全实现的Windows服务。
列表7.9 寄宿在一个Windows服务中WCF服务
using System.ComponentModel; |
using System.Configuration.Install; |
using System.ServiceProcess; |
using System.ServiceModel; |
using System.ServiceModel.Description; |
public class ProjectInstaller : Installer |
private ServiceProcessInstaller process; |
private ServiceInstaller service; |
public ProjectInstaller() |
process = new ServiceProcessInstaller(); |
process.Account = ServiceAccount.LocalSystem; |
service = new ServiceInstaller(); |
service.ServiceName = "EssentialWCF" ; |
public interface IStockService |
double GetPrice( string ticker); |
public class StockService : IStockService |
public double GetPrice( string ticker) |
public partial class Service : ServiceBase |
protected override void OnStart( string [] args) |
ServiceHost serviceHost = new ServiceHost( typeof (StockService)); |
ServiceEndpoint endpoint = serviceHost.Description.Endpoints[0]; |
EventLog.WriteEntry(endpoint.Contract.Name + "Started" + |
"listening on " + endpoint.Address + " (" + endpoint.Binding.Name + ")" , |
System.Diagnostics.EventLogEntryType.Information); |
protected override void OnStop() |
EventLog.WriteEntry( "EssentialWCF Stopping" , System.Diagnostics.EventLogEntryType.Information); |
图片7.5 显示了当EffectiveWCF服务启动时的服务控制管理器的截图。