WCF系列教程之WCF服務宿主與WCF服務部署


本文參考自http://www.cnblogs.com/wangweimutou/p/4377062.html,純屬讀書筆記,加深記憶。

一、簡介

任何一個程序的運行都需要依賴一個確定的進程中,WCF也不例外。如果我們需要使用WCF服務,那么我們就必須將服務寄宿與創建它並控制它的上下文和生存期的運行時環境當中,承載服務的環境,稱之為宿主。WCF服務可以在支持托管代碼的任意Windows進程中運行。WCF提供了統一編程模型,用於生成面向服務的應用程序。此編程模型保持一致且獨立於部署服務的運行時環境。 實際上,這意味着不管使用什么宿主選項,服務的代碼看起來都非常類似。

所以,WCF服務的宿主選項可以有多種選項:

(1)、控制台應用程序

(2)、服務器環境,如 Internet 信息服務 (IIS)

(3)、Windows 進程激活服務 (WAS) 管理的工作進程內運行的

(4)、Windows 服務

.

.

.

等等

開發人員可以選擇滿足服務部署要求的宿主環境。 這些要求可能源自部署應用程序的平台,它必須發送和接收消息的傳輸,或者進程回收的類型和為確保足夠可用性所需的其他進程管理,或者某些其他管理或可靠性要求。   

 

二、WCF宿主環境主要有以下幾種

1、托管應用程序中的自承載

WCF服務可以承載與任何托管應用程序中,這是最靈活的選項,因為它需要部署的基礎結構最少,在托管應用程序代碼內嵌入服務代碼,然后創建並打開 ServiceHost 的實例以使服務變為可用。

這種方式的方案主要有兩個:

(1)、控制台應用程序

(2)、客戶端應用程序

i、 Windows Presentation Foundation (WPF)

ii、 Windows 窗體 (WinForms) 應用程序

控制台的優勢:

在應用程序的開發階段中,將 WCF 服務承載於控制台應用程序內通常是很有用的。 這使服務變得容易調試,從中跟蹤信息以查明應用程序內發生的情況變得更加方便,以及通過將其復制到新的位置進行來回移動變得更加輕松。 

客戶端應用程序的優勢:

此宿主選項還使客戶端應用程序(如 WPF 和 WinForms 應用程序)與外部世界的通信變得很容易。 例如,一個將 WPF 用於其用戶界面並作為 WCF 服務主機的對等協作客戶端,允許其他客戶端連接到它並共享信息。

2、托管應用程序中的自承載代碼實例

(1)、控制台應用程序代碼實例

請參考WCF系列教程之WCF消息交換模式之單項模式

(2)、關於Windows Presentation Foundation (WPF)和Windows 窗體 (WinForms) 應用程序的代碼實例,因為本人不常用這兩種技術開發,所以不多做解釋

 

3、托管Windows服務

此宿主選項注冊WCF服務作為托管Windows服務(以前成為NT服務),承載與其中的應用程序域中,以便服務的進程生存期由 Windows 服務的服務控制管理器 (SCM) 控制。與自承載選項一樣,此類型的宿主環境要求作為應用程序的一部分編寫某些宿主代碼。 通過使服務從 ServiceBase 類以及從 WCF 服務協定接口繼承,將該服務同時實現為 Windows 服務和 WCF 服務。 然后創建 ServiceHost,在被重寫的 OnStart(String[]) 方法內打開它並在被重寫的 OnStop() 方法內關閉它。 還必須實現從 Installer 繼承的安裝程序類,以允許 Installutil.exe 工具將程序安裝為 Windows 服務。在未激活消息的安全環境中,由托管 Windows 服務宿主選項啟用的方案是承載於 IIS 之外、長時間運行的 WCF 服務的方案。 服務的生存期改由操作系統控制。 此宿主選項在 Windows 的所有版本中都是可用的。

3.1、Windows服務(以前成為NT服務)的優點:

(1)、承載在IIS外、長時間運行的WCF服務

(2)、受所有windows版本的支持

(3)、由操作系統控制控制服務進程的生存期

3.2、Windows服務(以前成為NT服務)支持的傳輸

(1)、HTTP

(2)、net.tcp

(3)、net.pipe

(4)、net.msmq

3.3、進程和AppDomain回收

不會被回收,除非手動關閉服務

 

4、托管Windows服務代碼示例

第一步:創建服務契約層IService(類庫),在新建兩個契約接口ICalculate和IMessage,具體代碼如下:

ICalculate.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.ServiceModel;
using System.Text;
using System.Threading.Tasks;

namespace IService
{
    [ServiceContract]
    public interface ICalculate
    {
        [OperationContract]
        int Add(int a, int b);
    }
}

IMessage.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.ServiceModel;
using System.Text;
using System.Threading.Tasks;

namespace IService
{
    [ServiceContract]
    public interface IMessage
    {
        [OperationContract]
        string ReturnMessage(string name);
    }
}

第二步:創建具體的服務層,並實現上面的契約接口,新建Calculate和Message兩個類

Calculate.cs

using IService;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Service
{
    public class Calculate : ICalculate
    {
        public int Add(int a, int b)
        {
            return a + b;
        }
    }
}

Message.cs

using IService;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Service
{
    public class Message:IMessage
    {

        public string ReturnMessage(string name)
        {
            return "Hello" + name;
        }
    }
}

第三步:創建宿主NTHost,新建windows服務

雙擊該文件,右鍵添加安裝程序,生成如下兩個文件

ok,服務配置完畢

第四步:編寫服務主程序,Service1代碼如下:

using Service;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Linq;
using System.ServiceModel;
using System.ServiceProcess;
using System.Text;
using System.Threading.Tasks;

namespace NTHost
{
    partial class Service1 : ServiceBase
    {
        public Service1()
        {
            InitializeComponent();
        }

        ServiceHost MessageHost = null;
        ServiceHost CalculatorHost = null;

        protected override void OnStart(string[] args)
        {
            MessageHost = new ServiceHost(typeof(Message));
            CalculatorHost = new ServiceHost(typeof(Calculate));

            MessageHost.Open();
            CalculatorHost.Open();
        }

        protected override void OnStop()
        {
            MessageHost.Close();
            CalculatorHost.Close();

            MessageHost = null;
            CalculatorHost = null;
        }
    }
}

第五步:編寫控制台主程序,代碼如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.ServiceProcess;
using System.Text;

namespace NTHost
{
    static class Program
    {
        /// <summary>
        /// 應用程序的主入口點。
        /// </summary>
        static void Main()
        {
            ServiceBase[] ServicesToRun;
            ServicesToRun = new ServiceBase[] 
            { 
                new Service1() 
            };
            ServiceBase.Run(ServicesToRun);
        }
    }
}

第六步:配置配置文件,App.config文件代碼如下:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <system.serviceModel>
    <services>
      <service name="Service.Message" behaviorConfiguration="mexBehavior">
        <host>
          <baseAddresses>
            <add baseAddress="http://localhost:2234/Message/"/>
          </baseAddresses>
        </host>
        <endpoint address="" binding="wsHttpBinding" contract="IService.IMessage" />
        <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
      </service>

      <service name="Service.Calculate" behaviorConfiguration="mexBehavior">
        <host>
            <baseAddresses>
              <add baseAddress="http://localhost:1235/ServiceCalculator/"/>
              <add baseAddress="net.tcp://localhost:1234/ServiceCalculator"/>
            </baseAddresses>
          </host>
         <endpoint address="" binding="netTcpBinding" bindingConfiguration="PortSharingBinding" contract="IService.ICalculate" >
          <identity>
            <dns value="localhost"/>
          </identity>
        </endpoint>
        <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
      </service>
    </services>

    <bindings>
      <netTcpBinding>
        <binding name="PortSharingBinding" portSharingEnabled="true" >
          <security mode="None" />
        </binding>
      </netTcpBinding>
    </bindings>

    <behaviors>
      <serviceBehaviors>
        <behavior name="mexBehavior">
          <serviceMetadata httpGetEnabled="true" />
          <serviceDebug includeExceptionDetailInFaults="false" />
        </behavior>
      </serviceBehaviors>
    </behaviors>

  </system.serviceModel>
</configuration>

第七步:應為本實例啟用的是net.tcp通訊,啟用net.tcp通訊就必須依靠Windows 進程激活服務(也稱為 WAS)在控制面板->程序和功能->打開或關閉windows功能勾選以下幾個功能,安裝WCF 激活組件

第八步:寄宿服務,生成NTHost工程,安裝windows服務程序NTHost.exe

在命令行中輸入Cd C:\Windows\Microsoft.NET\Framework\v4.0.30319,回車后輸入installutil.exe 程序生成的bin目錄絕對地址\NTHost.exe,回車后安裝服務程序,程序注冊成功后啟動服務。

第九步:打開wcftestclient客戶端進行測試

 

5、Internet信息服務(IIS)

在IIS中承載WCF服務,之前已經創建了契約層和服務層,這里就不創建了。

第一步:新建IISHost空Web應用程序,作為WCF服務的宿主

第二步:新建WebService服務

新建Calculate.svc,刪除多余的文件,代碼如下:

<%@ ServiceHost Language="C#" Debug="true"  Service="Service.Calculate" %>

新建Message.svc,刪除多余的文件,代碼如下:

<%@ ServiceHost Language="C#" Debug="true"  Service="Service.Message" %>

簡單解釋下上面代碼的意思,Debug=true,表示當前服務可調式,Service="Service.Message"指定當前服務的類型為Service.Message

第三步:配置配置文件,這里配置兩個服務一個是ServiceMessage用於Http通訊,一個是ServiceCalculator用於net.tcp通訊,Web.config文件代碼如下:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <system.serviceModel>
    <services>
      <service name="Service.Message" behaviorConfiguration="mexBehavior">
        <host>
          <baseAddresses>
            <add baseAddress="http://localhost:2234/Message/"/>
          </baseAddresses>
        </host>
        <endpoint address="" binding="wsHttpBinding" contract="IService.IMessage" />
        <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
      </service>

      <service name="Service.Calculate" behaviorConfiguration="mexBehavior">
        <host>
            <baseAddresses>
              <add baseAddress="http://localhost:1235/ServiceCalculator/"/>
              <add baseAddress="net.tcp://localhost:1234/ServiceCalculator"/>
            </baseAddresses>
          </host>
         <endpoint address="" binding="netTcpBinding" bindingConfiguration="PortSharingBinding" contract="IService.ICalculate" >
          <identity>
            <dns value="localhost"/>
          </identity>
        </endpoint>
        <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
      </service>
    </services>

    <bindings>
      <netTcpBinding>
        <binding name="PortSharingBinding" portSharingEnabled="true" >
          <security mode="None" />
        </binding>
      </netTcpBinding>
    </bindings>

    <behaviors>
      <serviceBehaviors>
        <behavior name="mexBehavior">
          <serviceMetadata httpGetEnabled="true" />
          <serviceDebug includeExceptionDetailInFaults="false" />
        </behavior>
      </serviceBehaviors>
    </behaviors>

  </system.serviceModel>
</configuration>

第四步:寄宿服務

生成IISHost程序,在生成前確保,IISHost引用了契約層和服務層,將bin文件目錄、ServiceCalculator.svc、ServiceMessage.svc、Web.config拷貝到新建的IISHost文件夾(作為網站發布)中,然后IISHost以網站的形式發布到IIS服務器上。

 

 

ok,網站配置完成

ok,說明Message.svc服務部署成功!

可以看到Calculate.svc服務寄宿失敗,這是因為ServiceCalculator.svc啟用的是net.tcp通訊,而在IIS中啟用net.tcp通訊就必須依靠Windows 進程激活服務(也稱為 WAS)

關於如何啟用net.tcp通訊,上面已經介紹過了,所以這里就不說了,ok,在net.tcp通訊啟用的情況下,配置承載服務的WCFHost網站,添加net.tcp通訊

點擊網站的高級設置,在已啟用的協議后追加net.tcp協議

 

重新打開Calculate.svc

ok,說明Calculate服務部署成功!

 

第五步:使用wcftestclicnt進行測試

ok,IIS作為宿主部署WCF服務成功!

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM