打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
ServiceHost与宿主寄存

我们已经知道,对于一个服务(接口),有ABC三个要素,通过他们可以被客户端利用来调用,可是在服务端,它的结构是怎么样的?

ServiceHost

WCF的服务可以有很多寄存环境,可是,不管在哪种环境,服务模型在宿主初始化,操作调用和消息处理方面,都提供一致的运行时体验。ServiceHost类型在这过程中扮演着重要的角色。

简单的可以认为ServiceHost负责管理服务的通信信道的生存周期。

建立ServiceHost

一般使用public ServiceHost(Type serviceType, params Uri[] baseAddresses)构造方法建立ServicesHost

参数:

Type serviceType --为实现了某些Contract的类的类型,为这个服务主机要host的服务。

params Uri[] baseAddresses --为任意数量的baseAddress。

Uri baseAddress = new Uri("http://localhost:8080/WCFService/Service");

//Instantiate new ServiceHost

myServiceHost = new ServiceHost(typeof(Service), baseAddress);

一个ServiceHost内只能驻留一个Service类,但是这个Service类可以实现多个Contract,每个Contract都能通过一个或多个(不同的bindEndpoint向客户端暴露。

通过两方法给ServiceHost添加Endpoint

ServiceHost.AddServiceEndpoint

AddServiceEndpoint方法有8种重载,ServiceHost提供了四种:

ServiceEndpoint AddServiceEndpoint(Type implementedContract, Binding binding, string address);

ServiceEndpoint AddServiceEndpoint(Type implementedContract, Binding binding, Uri address);

ServiceEndpoint AddServiceEndpoint(Type implementedContract, Binding binding, string address, Uri listenUri);

ServiceEndpoint AddServiceEndpoint(Type implementedContract, Binding binding, Uri address, Uri listenUri);

 

ServiceHost的父类ServiceHostBase也提供了四种:

ServiceEndpoint AddServiceEndpoint(string implementedContract, Binding binding, string address);

ServiceEndpoint AddServiceEndpoint(string implementedContract, Binding binding, Uri address);

ServiceEndpoint AddServiceEndpoint(string implementedContract, Binding binding, string address, Uri listenUri);

ServiceEndpoint AddServiceEndpoint(string implementedContract, Binding binding, Uri address, Uri listenUri);

 

其中参数implementedContract为Contract的完全名称,即名称空间.类名。

myServiceHost.AddServiceEndpoint(typeof(WCFService.IService), new BasicHttpBinding(), "");

ServiceHost.Description.AddServiceEndpoint

ServiceDescription是一个Service在内存中的一个完整描述。包括:EndPointsBehaviors

ServiceEndpoint myServiceEndpoint = new ServiceEndpoint(ContractDescription.GetContract(typeof(WCFService.IService)), new BasicHttpBinding(), new EndpointAddress(baseAddress));

myServiceHost.Description.Endpoints.Add(myServiceEndpoint);

视需要给ServiceHost添加behavior

ServiceHostBehaviors是一个 IServiceBehavior类型的对象集合。

IserviceBehavior提供了一个在整个服务范围内修改或则插入定制扩展的机制。

 

如果需要把服务通过WSDL对外暴露对服务的Metadata描述,就需要加一个ServiceMetadataBehavior类型的Behavior:

 

ServiceMetadataBehavior behavior = new ServiceMetadataBehavior();

behavior.HttpGetEnabled = true;

behavior.HttpGetUrl = new Uri("http://localhost:8001/");

myServiceHost.Description.Behaviors.Add(behavior);  // myServiceHost是ServiceHost实例

一个较规范(正确的)ServiceHost描述应该是这样的:

 

EndPointListener侦听器包含了listening addressmessage filteringduspatch。他们独赢ServiceEndpoint中的EndPointAddressContractBinding。在EndpointListener中,还包含了一个Channel Stack,专门负责发送和接受消息。

WCF系列(一) -- 完全不使用配置文件构建和使用WCF服务 

Windows Communication Foundation入门(Part Two
 

宿主

WCF典型的宿主包括以下四种:

Self-Hosting 自托管宿主

Managed Windows ServicesWindows 服务宿主)

Internet Information ServicesIIS宿主)

Windows  Process Activation ServiceWAS宿主)

1、自托管宿主利用

WCF提供的ServiceHost<T>提供的Open()Close()方法,可以便于开发者在控制台应用程序,Windows应用程序乃至于ASP.NET应用程序中托管服务。不管自宿主的环境是何种应用程序,实质上托管服务的方式都是一致的。例如在控制台应用程序中:

using (ServiceHost host = 

new ServiceHost(typeof(DocumentsExplorerService)))

{    host.Open();    

Console.WriteLine("The Service had been launched.");    

Console.Read();

}

由于ServiceHost实例是被创建在应用程序域中,因此我们必须保证宿主进程在调用服务期间不会被关闭,因此我们利用Console.Read()来阻塞进程,以使得控制台应用程序能够一直运行,直到认为地关闭应用程序。如果是Windows应用程序,则可以将创建ServiceHost实例的代码放在主窗体的相关代码中,保证服务宿主不会被关闭。相应地,我们需要配置应用程序的app.config配置文件:

<configuration>  

<system.serviceModel>    

<services>      

<service name="DocumentsExplorerServiceImplementation.DocumentsExplorerService" 

behaviorConfiguration="DocumentExplorerServiceBehavior">        

<host>          

<baseAddresses>            

<add baseAddress="http://localhost:8008/DocumentExplorerService"/>           </baseAddresses>       

 </host>                  

<endpoint          address=""          

binding="basicHttpBinding"          bindingConfiguration="DocumentExplorerServiceBinding"          contract="DocumentsExplorerServiceContract.IDocumentsExplorerService"/>        

<endpoint address="mex" 

binding="mexHttpBinding" contract="IMetadataExchange"/>             </service>    

</services>   

 <bindings>      

<basicHttpBinding>        

<binding name="DocumentExplorerServiceBinding" 

sendTimeout="00:10:00" transferMode="Streamed"                  

messageEncoding="Text" textEncoding="utf-8" maxReceivedMessageSize="9223372036854775807">                  </binding>      

</basicHttpBinding>    

</bindings>    

<behaviors>      

<serviceBehaviors>        

<behavior name="DocumentExplorerServiceBehavior">          

<serviceMetadata 

httpGetEnabled="true"/>                  

</behavior>      

</serviceBehaviors>    

</behaviors>  

</system.serviceModel>

</configuration>

注意,配置文件中的服务名必须包含服务契约以及服务类的命名空间。此外,在配置文件中我通过<baseAddresses>标签为服务添加了基地址,因此在endpoint中,address""。此时,调用服务的客户端配置文件也应与服务的配置保持一致:

注意,两个配置文件中的服务地址都是一样的,对于绑定的配置也基本一致。在通常的企业应用中,我们很少会采用自宿主方式托管服务,这是因为这种方式必须要在应用程序运行下,客户端才能够调用服务,且并不便于随时启动和停止服务。除了不具有易用性与易管理性之外,在可靠性、性能等诸多方面受到很多限制。但由于它简单、易于实现,因而往往用于开发期间的调试或演示环境。自托管宿主支持所有的绑定。

窗体底端

2、Windows Services宿主

Windows Services宿主则完全克服了自托管宿主的缺点,它便于管理者方便地启动或停止服务,且在服务出现故障之后,能够重新启动服务。我们还可以通过Service Control Manager(服务控制管理器),将服务设置为自动启动方式,省去了服务的管理工作。此外,Windows Services自身还提供了一定的安全性以及检测机制和日志机制

Windows Services宿主的实现也非常简单。我们可以在Visual Studio中创建Windows Services项目。在创建项目之后,就可以创建一个继承了System.ServiceProcess.ServiceBase类的Windows服务类。Windows服务类继承了ServiceBase类的OnStart()和OnStop()方法,完成Windows服务的启动与停止。我们可以重写这两个方法,将ServiceHost的启动与关闭对应地放入这两个方法的实现中。例如我们创建的DocumentsExplorerWindowsService类:
namespace BruceZhang.WCF.DocumentsExplorer
{
    public partial class DocumentsExplorerWindowsService : ServiceBase
    {
        private ServiceHost m_serviceHost = null;

        public static void Main()
        {
            ServiceBase.Run(new DocumentsExplorerWindowsService());
        }

        public DocumentsExplorerWindowsService()
        {
            InitializeComponent();
            ServiceName = "DocumentsExplorerService";
        }

        protected override void OnStart(string[] args)
        {
            if (m_serviceHost != null)
            {
                m_serviceHost.Close();
            }
            m_serviceHost = new ServiceHost(typeof(DocumentsExplorerService));
            m_serviceHost.Open();
        }

        protected override void OnStop()
        {
            if (m_serviceHost != null)
            {
                m_serviceHost.Close();
                m_serviceHost = null;
            }
        }


    }
}

在Main函数中,我们通过ServiceBase.Run()静态方法创建Windows服务实例,并在Windows服务类的构造函数中,调用ServiceBase类的ServiceName属性指定服务名。在重写的OnStart()方法中,我们首先判断是否已经存在ServiceHost实例,如果不存在,则创建它。创建ServiceHost实例的方法与自托管宿主方式相同。

为了完成ServiceHost实例的创建,我们同样需要在项目中添加app.config配置文件,配置文件的内容与前完全一样。

如果在企业应用中要使用WCF技术,最佳的宿主方式我认为就是Windows Services,尤其是服务器的操作系统不是Vista的情况之下。它便于服务的管理,能够维持服务长时期的运行,同时它还支持所有的绑定,因而受到的限制最小。然而,这种方式唯一的缺点却是对宿主的部署相对比较复杂,必须通过.NET提供的Installutil.exe工具完成对服务宿主的安装(也可以通过安装包的自定义操作完成)

若要完成对服务宿主的安装,我们还需要创建它的安装程序。我们可以自定义一个安装类,使其继承自System.Configuration.Install.Installer类。更简单的办法则是通过Windows服务提供的设计时支持,直接创建安装类。方法是在Windows服务例如DocumentsExplorerWindowsService的设计器视图下,通过单击右键,在快捷菜单中选择“Add Installer”,如图二所示:

 
图二   添加安装程序

创建的安装程序ExplorerServiceInstaller如下所示:
namespace BruceZhang.WCF.DocumentsExplorer
{
    //Type services.msc to access the Service Control Manager(SCM) and browse the windows services
    //Type installutil /u filename to uninstall the windows service
    [RunInstaller(true)]
    public partial class ExplorerServiceInstaller : Installer
    {
        private ServiceProcessInstaller m_process;
        private ServiceInstaller m_service;
        public ExplorerServiceInstaller()
        {
            InitializeComponent();

            m_process = new ServiceProcessInstaller();
            m_process.Account = ServiceAccount.LocalSystem;
            m_service = new ServiceInstaller();
            m_service.ServiceName = "DocumentsExplorerService";
            Installers.Add(m_process);
            Installers.Add(m_service);
        }
    }
}

在ExplorerServiceInstaller类中,ServiceAccount是一个枚举类型,可以设置为LocalService,LocalSystem,NetworkService以及User值。其中,LocalService的安全性最低,User值的安全性最高,需要有效的用户账号方才可以安装服务。

对于安装程序而言,也可以直接在设计器视图下设置它的属性。

安装程序直接建立在Windows服务的程序集中,编译之后会获得一个exe文件,例如DocumentsExplorer.exe。然后,我们通过在Visual Studio的Command Prompt模式下运行如下命令:
installutil DocumentsExplorer.exe
即可完成对服务宿主的安装。

打开服务控制管理器(可以在Command Prompt模式下输入Services.msc打开),可以看到名为DocumentsExplorer

Service的服务:
 
图三  服务控制管理器

如果要卸载该服务宿主,可以通过installutil的/u开关卸载。
在企业应用中,我们往往会将该Windows服务设置为自动启动,可以简化管理员的工作。

关于如何使用ServiceBase

http://msdn.microsoft.com/en-us/zt39148a(zh-cn,VS.80).aspx

3IIS宿主(说明,这里讲的IISIIS 6.0
若要使用IIS宿主,需要为程序集中添加一个svc文件。我们可以通过为项目添加一个新项的方式添加svc文件:

4、WAS宿主
WASIIS 7.0的一部分,但也可以独立地安装与配置。WAS支持所有可用的WCF传输协议、端口与队列。
利用WAS托管服务与IIS宿主托管服务的方法并没有太大的区别,仍然需要创建svc文件,同时在IIS中需要在站点中创建应有程序指向托管应用程序,还可以设置访问服务的别名与应用程序池。
由于WAS诉诸支持所有的绑定,因此此时的服务绑定并不会受到宿主的限制。

如何创建一个标准的Windows服务 

WCF宿主与服务托管

本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
Windows Communication Foundation入门(Part Two) ...
Integrating Windows Workflow Foundation and Windows Communication Foundation (转于 MSDN)
WCF中的ServiceHost初始化两种方式
WCF基础(转)
WCF: Host、Client、MetadataExchage
WCF Tutorial
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服