簡介
如果企業依賴於面向服務的體系結構,就必須確保服務能夠正常可靠的運行。應用程序可靠性背後最重要的動因是在哪裡托管服務以及如何托管服務。在考慮托管服務時,您必須事先考慮幾個問題:服務有哪些可用性方面的要求?如何管理和部署服務?是否需要提供對舊版本服務的支持?
了解如何滿足這些業務要求對於開發成功的服務是至關重要的。在第 3 章中您將了解到,必須自己提供宿主來承載服務。Windows Communication Foundation (WCF) 本身沒有附帶宿主,而是提供了一個被稱為 ServiceHost的類,該類允許您在自己的應用程序中承載 WCF服務。您不必考慮任何網絡傳輸方面的細節,即可確保服務能夠被訪問。只需以編程方式或聲明方式對服務的端點進行配置,然後調用 ServiceHost的Open 方法即可。ServiceHostBase和ServiceHost中集成了第 3 章要介紹的有關綁定、通道、調度程序和偵聽器的所有一般功能。這意味著用於承載服務的應用程序(運行 ServiceHost的應用程序)的負載將遠遠低於您之前預期的水平。
本章討論何種類型的應用程序可以為 ServiceHost 提供宿主環境。此外,您還會對使用不同應用程序內承載的服務時存在的差異有所了解。
讀完本章後,您將學到以下知識:
◆適用於您的各種不同的承載方案
◆每種承載方案有哪些優點和缺點
◆根據具體情況選擇承載方案的指導
◆有關 Microsoft 如何實現不同承載方案以及每種方案在哪些方面具有可擴展性的體系結構方面的指導
研究承載方案
在Microsoft .NET 平台上,使用 Microsoft Visual Studio.NET 可以創建幾種不同類型的托管 Windows 應用程序:
◆WinForms 應用程序
◆控制台應用程序
◆Windows服務
◆承載於 Internet 信息服務 (IIS)中的Web 應用程序 (ASP.NET)
◆IIS 7.0內提供的WCF服務以及 Windows Vista或Windows Server 2007中的WAS
如果您仔細研究 Microsoft Visual Studio 2005 附帶的項目模板,就會發現還有其他可選方案供您使用。很顯然,我們認為沒有其他模板可以在服務世界中用作可行的方案。但值得注意的是,只要 WCF 能夠提供 .NET 應用程序域,您就可以在其他任何類型的應用程序中運行服務。(如果您不了解 .NET 應用程序域的原理,請參考下面“了解 .NET 應用程序域”一節的有關內容。)實際上這完全取決於您對宿主的要求。總結這些可選方案,我們主要考慮以下三類常見的WCF服務宿主:
◆在托管的.NET 應用程序中進行自承載
◆在Windows服務中進行承載
◆在不同版本的IIS中進行承載
可想而知,如本節之前提到的,所有這些宿主在Visual Studio中都有相關聯的項目模板,並且都有自己的特征。要想更好地了解在每種情況下哪種宿主是最佳選擇,必須了解宿主通常的要求和功能。理解這一點後,我們將分別詳細介紹每種承載方案。
了解 .NET 應用程序域
如果您了解 Windows進程的角色以及如何通過托管代碼與它們交互,那麼您肯定會對.NET 應用程序域的概念有所了解。要在進程中運行托管 .NET 代碼,就需要創建程序集。這些程序集並不直接承載於 Windows進程中。而是由公共語言運行庫 (CLR) 在進程中創建稱為“應用程序域”的單獨邏輯分區來對托管代碼進行隔離。單個進程可能會包含多個應用程序域,每個域都會承載封裝於程序集內的不同代碼片斷。這種對傳統 Windows進程的劃分方式可以通過 .NET Framework 提供幾個好處。
主要好處如下所示:
◆由於不涉及可執行文件或庫的概念,應用程序域決定了 .NET 平台的與操作系統無關的特性。
◆您可以根據自身需要控制、卸載和加載應用程序域。
◆應用程序域在應用程序或多個應用程序域共生的進程中起到隔離的作用。進程中的應用程序域彼此相互獨立,雖然一個域出現故障,但其他域仍可正常工作。
承載環境特征
.NET 應用程序需要一個作為宿主的Windows進程。該 Windows進程內部可以承載多個 .NET 應用程序域。應用程序域是 .NET CLR 將托管代碼與 Windows進行隔離所采用的一種手段。CLR 會在每個工作進程中進行初始化,並自動創建一個默認的應用程序域。該默認應用程序域運行於某個進程,並直到該進程結束時才會卸載。默認應用程序域的關閉是由 CLR 來控制的。在大多數宿主中,默認應用程序域內部並不運行任何代碼。而是由宿主(或“進程”)來新建應用程序域,以便應用程序域可以獨立於進程而關閉。在很多應用程序中,理想的情況是客戶端代碼和服務器端代碼分別在不同應用程序域中執行。通常這種要求是出於安全性和隔離等原因的考慮。
進程和應用程序域之間的關系類似於應用程序和應用程序域與 ServiceHostWCF 之間的關系。如圖 5-1 所示,每個進程都至少有一個應用程序域,並且每個應用程序域都可以承載零個或更多的WCF ServiceHost 實例。WCF 需要一個 Windows進程內部至少要承載一個應用程序域。
圖 5-1:進程、應用程序域和 WCF ServiceHost 關系
注意:盡管可以實例化多個 ServiceHost 實例,但每個應用程序域內保留一個 ServiceHost 實例更便於操作。您可以在一個宿主內使用多個端點公開多個服務接口。更高級的宿主(例如,IIS和WAS)確實可以實例化多個 ServiceHost 實例,以提供隔離和不同的安全上下文。
因此,宿主的主要任務是向WCF ServiceHost 提供 Windows 工作進程和應用程序域。此外,WCF 依賴於應用程序域提供的安全和配置功能。Windows進程始終使用默認標識運行,WCF服務可隨時使用這個現成的標識。但是,WCF 提供了幾個級別的模擬用戶的功能(詳見本書第 7 章)。如果您不使用這些功能,則由運行服務的Windows進程提供安全上下文。前面幾章提到過,默認情況下 WCF 依賴於 .NET Framework中的配置功能,您可以通過應用程序域對其進行訪問。
某些宿主還具有管理所運行的應用程序的其他功能。最為突出的是,IIS 還具備自動進程回收、資源限制、日志記錄、運行狀況指示器等其他功能。您可以通過整個章節的學習了解有關這些主題的詳細內容。(不同 IIS 版本具有受 WCF 支持的不同的可管理性功能。最為明顯的,Windows XP中的IIS 5.1 在管理用戶界面方面就受到一些限制。)
承載環境特征
Microsoft 在確保服務開發人員無需過分考慮承載環境方面所做的努力是值得肯定的。ServiceHost 排除了所有技術性的難點,使您可以重點關注服務邏輯,而不必過多地考慮如何承載服務。您必須根據自己的具體要求選擇一個宿主。WCF 主要是作為編程模型而編寫的,其主要設計目的之一是為了實現“宿主的不可知”。ServiceHost 不關心自身在哪裡被實例化,只要您希望服務可被訪問時它正在運行即可。也就是說,它需要一個運行 .NET 應用程序域的進程。
在選擇應用程序類型時,必須考慮某些特定要求(例如,程序屬於控制台應用程序還是 WinForms 應用程序等)。ServiceHost 必須被實例化才能提供運行服務所需的承載環境。典型的.NET 應用程序(例如,控制台應用程序和 WinForms 應用程序)通常運行在用戶桌面計算機上。這些環境並非始終運行,它們可以承載您的服務,但卻並非典型的適用於企業的宿主。我們認為適用於企業的宿主應該能夠支持更大規模的面向服務的體系結構,在這種體系結構中,多個系統需要依賴服務所公開的關鍵業務功能。這些適用於企業的宿主通常能夠滿足諸如高可用性的要求。因此,我們不能將控制台或 WinForms 應用程序做為適用於企業的宿主。
通常情況下,服務運行在服務器上,並由操作員進行管理和操作。管理服務器的操作員一般不希望在服務器重新啟動時手動啟動控制台應用程序或 WinForms 應用程序。為了讓服務應用程序能夠在數據中心運行,對於企業級面向服務的情況來說,唯一可行的方案就是在IIS 上承載服務,或將其作為一項 Windows服務。
有時,您需要在用戶的桌面計算機上實現進程間通信。在這種情況下,只有當用戶使用應用程序時,服務才是活動的。需要進行進程間通信的典型應用程序就是控制台應用程序和 WinForms 應用程序。這些應用程序適合承載這些類型的服務。
要能夠確定哪種宿主最適合您的情況,您應當考慮到非功能性要求。一般來講,非功能性要求規定了應用程序的技術要求,以確保其達到應用程序要求的質量和可維護性。對於 WCF 應用程序來說,非功能性要求實際涉及以下內容:
◆可用性:希望何時能夠訪問您的服務?
◆可靠性:當服務由於某些原因出現中斷時會發生什麼問題?這將如何影響服務的其他使用者?
◆可管理性:是否需要便捷地了解承載 WCF服務的宿主上所發生的情況?
◆版本控制:是否需要提供對舊版本服務的支持?是否知道誰在使用您的服務?
◆部署:要采用何種部署模型?是否要通過 Microsoft Installer進程和 Visual Studio 部署包進行安裝,還是使用 xcopy 就可以滿足需要?
◆狀態:服務是無狀態的嗎?是否需要會話?
根據這些非功能性要求,您可以確定哪些宿主是符合您的需求的。為了幫助您做出選擇,本章後面的內容將介紹不同的承載環境及其優缺點。
注意:由於對自身的運行環境並不了解,因此 WCF 編程模型總是有可能切換到不同宿主,但這並不意味著您必須更改服務實施。首先,您需要在控制台應用程序中進行自承載,以測試並確定服務的原型。
自承載您的服務
承載 WCF服務最靈活、最便捷的方法就是進行自承載。要能夠自承載服務,必須滿足兩個條件。第一,需要 WCF 運行時;第二,需要可以承載 ServiceHost的托管 .NET 應用程序。您需要自己動手編寫啟動和停止宿主的代碼。
下面是自承載的優點:
◆易用性:只需幾行代碼即可使服務運行。
◆靈活性:通過 ServiceHost的Open()和Close() 方法,可以輕松控制服務的生存期。
◆易調試性:可以使用熟悉的調試方式對自承載環境中承載的WCF服務進行調試,而不必連接到單個應用程序來激活服務。
◆易部署性:通常,部署簡單 Windows 應用程序與使用 xcopy 一樣容易。您不必在服務器場和類似地方部署復雜的方案,即可部署簡單的Windows 應用程序來充當 WCF ServiceHost。
◆支持所有綁定和傳輸:自承載並不限制您僅能使用現有的綁定和傳輸技術。在Windows XP和Windows Server 2003 上,IIS 限制您只能使用 HTTP。
下面是自承載的缺點:
◆可用性受到限制:服務只有在應用程序運行時才能被訪問。
◆功能受到限制:自承載的應用程序在對高可用性、易管理性、可靠性、可恢復性、版本控制和部署方案的支持方面受到一定限制。至少,現有的WCF 無法提供這些支持,因此在自承載的情況中,您必須自己實現這些功能;例如,默認情況下 IIS 提供了這些功能中幾項。
換句話說,對於企業級方案來說不應考慮自承載方式。自承載適用於企業項目的開發或演示階段。此外,當您希望用戶桌面應用程序進行相互通信或在點對點情況下,可以對服務進行自承載。本書第 12 章對此進行了描述。
第 3 章介紹了幾個自承載的方案示例,這些示例全都使用簡單的控制台應用程序。為了在實際工作環境中更好地說明自承載,本章提供了一個 WinForms 應用程序,該程序所承載的服務用於跟蹤 QuickReturns Ltd. 案例研究中證券商發布的報價。
在此方案中,有兩個不同的WinForms 應用程序。一個是證券商管理器應用程序,證券商可以使用該程序發布報價並進行證券交易。另一個程序是單獨的WinForms 應用程序,用於跟蹤發布的報價。如列表 5-1 所示,該程序公開一個服務,所公開的服務實現了 ITradeTrackingService 約定,從而實現對報價的跟蹤。證券商管理器應用程序會在成功通過 TradeService 發布報價後調用該服務。
列表 5-1:TradeTrackingService的ServiceContract
using System.ServiceModel;
using QuickReturns.StockTrading.ExchangeService.DataContracts;
namespace QuickReturns.StockTrading.TradeTrackingService.Contracts
{
[ServiceContract()]
interface ITradeTrackingService
{
[OperationContract()]
void PublishQuote(Quote quote);
}
}
在Windows服務中進行承載
在Windows服務中承載 WCF服務是一種合理的選擇。不應將 Windows服務與 WCF服務混為一談。它們都使用“服務”一詞,但卻具有不同的含義。Windows服務是由操作系統管理的進程。Windows 提供了服務控制管理器,用於控制操作系統上安裝的服務。Windows 通過服務來支持諸如網絡、USB、遠程訪問、消息隊列等操作系統功能。您可以使用 Visual Studio 2005,利用 Windows服務項目模板(如圖 5-2 所示)創建 Windows服務。
圖 5-2:Visual Studio 2005 Windows服務項目模板
Windows服務項目模板會生成一個項目,其中包含兩個文件:service1.cs文件和 program.cs文件。其中 service1.cs文件包含服務實現,而program.cs文件則用於實例化並實質上承載 Windows服務。要在Windows服務內部承載 WCF服務,只需執行 Windows服務的Start() 方法和 Stop() 方法,如列表 5-2 所示。由於啟動 Windows服務的范例與啟動 WCF ServiceHost內的服務相似,因此最後需要將 WCF服務的生存期與 Windows服務的生存期相連。
列表 5-2:承載 WCF ServiceHost的Windows服務
using System;
using System.ServiceModel;
using System.ServiceProcess;
using QuickReturns.StockTrading.ExchangeService;
namespace QuickReturns.StockTrading.ExchangeService.Hosts
{
public partial class ExchangeWindowsService : ServiceBase
{
ServiceHost host;
public ExchangeWindowsService()
{
InitializeComponent();
}
protected override void OnStart(string[] args)
{
Type serviceType = typeof(TradeService);
host = new ServiceHost(serviceType);
host.Open();
}
protected override void OnStop()
{
if(host != null)
host.Close();
}
}
}
由此可見,編寫用於承載 WCF服務的Windows服務非常容易,而且與本章前面的自承載方案相比,它還有幾個好處。另一方面,編寫承載 WCF服務的Windows服務也有一些您必須了解的缺點。
首先讓我們看一下優點:
◆可以自動啟動:Windows服務控制管理器允許將啟動類型設置為自動,從而可以在Windows 啟動立即啟動服務,而不必在計算機上進行交互登錄。
◆可以恢復:Windows服務控制管理器內建了對發生失敗後重新啟動服務的支持。
◆安全標識:Windows服務控制管理器允許您選擇運行服務所使用的特定安全標識,包括內置的系統或網絡服務帳戶。
◆可管理性:通常情況下,Windows 操作員對那些用於進行 Windows服務安裝和配置的服務控制管理器和其他管理工具都非常熟悉。這將使 Windows服務在實際工作環境中更容易被采納;但是,為了保證服務的可維護性,您可能需要添加某些檢測和日志記錄功能。
◆支持所有綁定和傳輸:自承載並不限制您僅能使用現有的綁定和傳輸技術。在Windows XP和Windows Server 2003 上,IIS 限制您只能使用 HTTP。
接下來是Windows服務的一些缺點:
◆部署: 必須通過 .NET Framework Installutil.exe 實用工具或通過安裝包中的自定義操作來安裝服務。
◆功能受到限制:Windows服務在對高可用性、易管理性、版本控制和部署方案的支持方面同樣也受到一定限制。實際上,您必須自己編寫自定義代碼來滿足這些要求,而IIS 在默認情況下就帶有這些功能的其中幾項。Windows服務確實添加了可恢復性和一些安全功能,但有些任務仍然需要您親手去做。
要能夠在服務控制管理器中安裝服務,必須在項目中添加安裝程序。Visual Studio 2005 允許您方便地完成該操作:
1、在Windows服務項目中打開 Service 類的設計器視圖。
2、單擊設計器背景以選擇服務本身,而並非其任何內容。
3、在“屬性”窗口中,單擊屬性列表下灰色區域中的“添加安裝程序”鏈接,如圖 5-3 所示。默認情況下,該操作將在項目中添加一個包含兩個安裝程序的組件類。組件名為 ProjectInstaller,它包含的安裝程序是服務的安裝程序和該服務相關進程的安裝程序。
圖 5-3:Windows服務項目的“添加安裝程序”功能
4、訪問 ProjectInstaller的設計器視圖,並單擊 ServiceInstaller1。
5、在“屬性”窗口中,將“ServiceName”屬性設置為“QuickReturns Exchange服務”。
6、將“StartType”屬性設置為“自動”,如圖 5-4 所示。
圖 5-4:QuickReturns Exchange服務的屬性窗口
7、訪問 ProjectInstaller的設計器視圖,並單擊“serviceProcessInstaller1”。
8、在“屬性”窗口中,將“帳戶”屬性設置為“網絡服務”,如圖 5-5 所示。
圖 5-5:QuickReturns Exchange服務的屬性窗口
為了能夠創建可用於安裝 Windows服務的安裝程序,必須向解決方案添加 Visual Studio 安裝程序和部署項目。以下步驟描述了如何向解決方案添加安裝程序和部署項目:
1、選擇“文件” | “添加” | “新建項目”。
2、在“新建項目”對話框中,選擇“其他項目類型”類別,選擇“安裝和部署”,然後選擇“安裝項目”,如圖 5-6 所示。
圖 5-6:Visual Studio 2005 安裝項目模板
3、在解決方案資源管理器中,右鍵單擊安裝項目,指向“添加”,然後選擇“項目輸出”,如圖 5-7 所示。此時將顯示“添加項目輸出組”對話框。
圖 5-7:添加 Windows服務項目輸出
4、選擇 Windows服務項目。
5、從列表框中,選擇“主輸出”,然後單擊“確定”。
此操作將向安裝項目添加 Windows服務的主輸出的項目項。現在,添加用於安裝可執行文件的自定義操作。若要向安裝項目添加自定義操作,請執行以下步驟:
1、在解決方案資源管理器中,右鍵單擊安裝項目,指向“視圖”,然後選擇“自定義操作”,如圖 5-8 所示。此時將顯示“自定義操作”視圖。
圖 5-8:打開“自定義操作”視圖
2、右鍵單擊“自定義操作”,選擇“添加自定義操作”。
3、雙擊列表框中的應用程序文件夾將它打開,從Windows服務項目中選擇“主輸出”,然後單擊“確定”。主輸出將添加到自定義操作的所有四個節點中:安裝、提交、回滾和卸載。
4、生成安裝項目。
編譯項目時,輸出的是 Microsoft 安裝程序文件 (.msi) ,通過該文件可以將服務安裝到 Windows服務控制管理器中。
注意 本章介紹生成 Windows服務和 Windows服務安裝程序的基礎知識。如果將 Windows服務設置為在不受限制的Localsystem 帳戶下運行或基本合適的網絡服務帳戶下運行,就安全最佳方法而言,這並非最佳選擇。通常,操作員能夠在安裝期間選擇憑據,或在安裝之後通過服務控制管理器管理控制台管理單元(可以通過 Windows 計算機管理進行訪問)來調整安全標識設置。有關開發 Windows服務的詳細信息和最佳方法,請參閱本書第 7 章、MSDN 幫助或 .NET 開發專著。
使用 Internet 信息服務進行承載
在IIS 上的Web服務開發長期以來一直是 ASP.NET的領地。ASP.NET 1.0 發布後,Web服務框架成為它的一部分。Microsoft 利用 ASP.NET HTTP 管道使 Web服務在Windows 平台上成為現實。遺憾的是,ASP.NET和Web服務之間的這種緊密耦合在面向服務的世界中產生了幾個限制,對HTTP的依賴性是主要原因。在不同宿主上運行 ASP.NET HTTP 管道很困難,因此很少采用這種方案。甚至在此後,ASP.NET Web服務(也稱為 ASMX服務)在部署方案和配置依賴性方面一直是非常面向Web的。Microsoft 最初發布了幾個版本的Web服務增強 (WSE),以彌補 ASP.NET Web服務的某些局限,尤其是消除在實現 WS-* 協議方面的限制。但是,WSE 非常依賴於 ASP.NET Web服務實現。
在以前幾章中介紹過,WCF服務采用了完全不同的途徑來實現面向服務。WCF的統一編程模型基於嚴格分層的模型,以分解面向Web的范例,並使服務模型和通道層與受支持的傳輸方式斷開連接。此模型允許 WCF 支持幾個不同的宿主,其中 IIS 是最重要的。
構建 WCF 是為了支持Windows XP、Windows Server 2003、Windows Vista和Windows Server 2007。自從IIS 5.1(與 Windows XP 一起發布)以來,有了很多變化。但是,Microsoft 仍然繼續支持舊版上的WCF。這可能是因為 Microsoft .NET Framework和CLR 提供的功能所導致的,該功能是構建 WCF的基礎。在以下幾節中,將介紹不同 IIS 版本的進程模型之間的差異和 WCF服務的結果。
IIS 5.1和IIS 6.0 核心功能
為了能夠解釋這些差異,我們首先必須解釋 IIS的核心功能。IIS 長期以來一直支持在一個計算機上運行多個站點和多個應用程序。為了做到這一點,IIS 引入了公用地址模型,該模型分為三個主要區域:
◆站點(注意:與 Windows XP 一起發布的IIS 5.1只支持一個站點。)
◆應用程序
◆虛擬目錄
站點綁定到特定方案、網絡地址和端口組合。IIS 不僅支持HTTP,而且依據版本還支持FTP、NNTP和SMTP。可以在相同站點下和在相同方案、網絡和端口組合下運行多個應用程序。應用程序的典型 URI 是 http://localhost/MyApplication。虛擬目錄只是映射到站點網絡空間的文件夾,它可以是文件系統中的其他某處。這樣,就可以使應用程序的實際內容或代碼與作為相同站點組成部分的其他應用程序分隔開來。
在IIS 6.0中,Microsoft對IIS進程模型做了一些重要更改。IIS進程模型被拆分成可以由站點和應用程序共享的應用程序池,在這裡,每個應用程序都運行在它自己的應用程序域中。“應用程序池”是稱為 W3wp.exe的單獨 Windows 工作進程,並且只在它需要啟動時才會啟動。換句話說,IIS 帶有應用程序激活模型,它允許 IIS 在它收到與應用程序池綁定的特定應用程序的請求時啟動該應用程序池。這樣,IIS 就能在一個服務器上承載數千個應用程序,而不必一直運行數千個進程。IIS的激活體系結構在服務世界中是有趣的模型,本章的“Windows 激活服務”節將對此進行介紹。
圖 5-9 顯示在HTTP 協議堆棧底部的IIS 6.0 核心體系結構以及在其頂部的至少四個不同進程。
圖 5-9:IIS 6.0 核心體系結構
◆Lsass.exe: 負責 IIS的安全功能:實現 Windows 身份驗證和安全套接字層 (SSL)。
◆Inetinfo.exe: 承載非 HTTP服務和 IIS Admin服務(包括元數據庫)的進程。
◆SvcHost.exe: 可以承載操作系統服務的進程;在使用 IIS的情況下,它承載 Web (HTTP)服務。
◆W3wp.exe: 工作進程。IIS 可以有多個 W3wp.exe進程,每個應用程序池一個。若要支持在單獨進程中拆分一個應用程序的Web 園方案,則有多個相同工作進程的實例。這可以提供額外的可伸縮性和性能優勢。
注意:我們要在這裡描述 IIS 6.0 體系結構,因為它是發布 WCF 之前最廣泛使用的IIS 版本。此外,WCF 支持IIS 6.0,並且該模型與使用 IIS 7.0和Windows 激活服務時選擇的實現非常類似,本章後面將對此進行介紹。IIS 5.1和IIS 6.0 之間的主要差異是站點和應用程序池的數量受到限制。IIS 5.1只支持綁定到一個應用程序池的一個站點。
在IIS中承載 WCF服務
若要在IIS中承載 WCF服務,需要有一個擴展名為 .svc的新物理文件。該文件將服務與其實現相關聯,並且是 IIS 自動創建 ServiceHost的手段。IIS 將接管服務與 ServiceHost 之間的交互,不必再由您自己實例化和啟動 ServiceHost。.svc文件的第一行包含一條夾在ASP.NET 指令內的指令,用於告訴承載環境此文件指向哪個服務。然後,服務代碼可以駐留在內嵌代碼行內(如列表 5-3 所示)、在注冊於 GAC的單獨程序集中、在駐留於應用程序的Bin文件夾內的程序集中、或者在駐留於應用程序的App_Code文件夾下的C#文件中。最常見方案是在配置文件中定義端點。在IIS中,必須在Web.config文件中定義端點,下一節將對此進行解釋。
列表 5-3 顯示一個基於前面的TradeService服務的示例 .svc文件。它有內嵌於代碼行內的服務代碼。列表 5-4 顯示一個示例 .svc文件,其中,代碼駐留於 App_Code文件夾內。
列表 5-3:包含內嵌代碼的ExchangeServiceInline.svc文件
<%@ServiceHost Language="C#"
Service="QuickReturns.StockTrading.ExchangeService.TradeServiceInline"
%>
using System;
using System.Collections;
using System.ServiceModel;
using QuickReturns.StockTrading.ExchangeService.Contracts;
using QuickReturns.StockTrading.ExchangeService.DataContracts;
namespace QuickReturns.StockTrading.ExchangeService
{
[ServiceBehavior(InstanceContextMode=InstanceContextMode.Single,
IncludeExceptionDetailInFaults=true)]
public class TradeServiceInline : ITradeService
{
public Quote GetQuote(string ticker)
{
...
}
public void PublishQuote(Quote quote)
{
...
}
}
}
列表 5-4. 包含外部代碼的ExchangeService.svc文件
<% @ServiceHost language="C#"
Service=" QuickReturns.StockTrading.ExchangeService.TradeService"
CodeBehind="~/App_Code/TradeService.cs" %>
在IIS中配置 WCF服務
在IIS中進行承載意味著您必須在要承載服務的應用程序的Web.config文件中設置 WCF 配置。Web.config文件中的服務配置類似於自承載服務。列表 5-5 顯示一個 TradeService服務的Web.config 示例文件。
列表 5-5:用於配置 IIS中承載服務的Web.config
<?xml version="1.0"?>
<configuration xmlns="http://schemas.microsoft.com/.NetConfiguration/v2.0">
<system.serviceModel>
<services>
<service
name="QuickReturns.StockTrading.ExchangeService.TradeService"
behaviorConfiguration="tradeServiceBehavior">
<endpoint name="basicHttpBinding"
address=""
binding="basicHttpBinding"
contract="QuickReturns.StockTrading.ExchangeService.?
Contracts.ITradeService"/>
<endpoint name="mexHttpBinding"
contract="IMetadataExchange"
binding="mexHttpBinding"
address="mex" />
</service>
<service
name="QuickReturns.StockTrading.ExchangeService.TradeServiceInline"
behaviorConfiguration="tradeServiceBehavior">
<endpoint name="basicHttpBinding"
address=""
binding="basicHttpBinding"
contract="QuickReturns.StockTrading.ExchangeService.?
Contracts.ITradeService"/>
<endpoint name="mexHttpbinding"
contract="IMetadataExchange"
binding="mexHttpBinding"
address="mex" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="tradeServiceBehavior" >
<serviceMetadata httpGetEnabled="true" />
</behavior>
<behavior name="returnFaults"
returnUnknownExceptionsAsFaults="true"/>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
</configuration>
請注意,服務的address 屬性為空。.svc文件確定服務的base 地址。但是,可以提供其他字符串用於設置相對於 .svc文件的端點地址。例如,可以使用以下格式:
http://localhost:8080/QuickReturns/Exchange.svc/ExchangeService
在配置文件中指定的服務 name 屬性充當了對應於 ExchangeService.svc的查找鍵,它告訴承載環境此配置屬於哪個服務。端點級別的其他屬性與前面的解釋相同。
在IIS中,Web 配置文件可以嵌套在站點、應用程序和虛擬目錄內。WCF 將接受所有配置文件,並將服務及其端點合並在一起。這意味著,嵌套的Web.config文件將相互疊加,在層次結構的底部讀取的最後一個文件優先於在層次結構中更高的文件。
在IIS中訪問 ServiceHost
在IIS中承載 WCF服務的默認行為是該 IIS 控制 ServiceHost的實例化。這將使您無法在消息到達服務之前有啟動和關閉代碼。當然,無啟動和關閉代碼的優點是可以減少可能引起錯誤的代碼。IIS 為您提供了在代碼行方面比控制台應用程序更容易的承載環境。但是,有時仍然需要有避免此限制的手段。要在實例化 ServiceHost 時這樣做並影響 IIS,可以建立您自己的工廠,用於創建自定義宿主。這樣,就可以訪問任何事件或改寫任何方法。
為了支持自定義 ServiceHost 激活,應當實現自己的Factory,它繼承自 ServiceHostFactory,這是可以實例化自定義宿主的工廠類。提供該類是為了關聯 ServiceHost的事件。您可以使用該類並將該類型作為 Factory 屬性放在.svc文件中,如列表 5-6 所示。通過改寫 ServiceHostFactory 類的CreateServiceHost 方法,可以執行與在自承載方案中相似的任務,第 3 章對此進行了介紹。在其他方面,這將使您能夠抽象邏輯,以便從外部配置建立說明,或為要使用的基礎庫、項目、部門或公司創建更合適的基類。
列表 5-7 顯示用於創建宿主的TradeServiceCustomHost和TradeServiceCustomHostFactory的代碼。
列表 5-6:包含 CustomServiceHostFactory的.svc文件
<% @ServiceHost Language="C#" Debug="true"
Service="QuickReturns.StockTrading.ExchangeService.TradeService"
Factory="QuickReturns.StockTrading.ExchangeService.
TradeServiceCustomHostFactory" %>
列表 5-7:TradeServiceCustomHostFactory和TradeServiceCustomHost
using System;
using System.ServiceModel;
using System.ServiceModel.Activation;
namespace QuickReturns.StockTrading.ExchangeService
{
public class TradeServiceCustomHostFactory : ServiceHostFactory
{
protected override ServiceHost CreateServiceHost(
Type serviceType, Uri[] baseAddresses)
{
TradeServiceCustomHost customServiceHost =
new TradeServiceCustomHost(serviceType, baseAddresses);
return customServiceHost;
}
}
public class TradeServiceCustomHost : ServiceHost
{
public TradeServiceCustomHost(Type serviceType, params Uri[]
baseAddresses)
: base(serviceType, baseAddresses)
{
}
protected override void ApplyConfiguration()
{
base.ApplyConfiguration();
}
}
}
回收
在IIS中承載 WCF服務時,WCF服務可以使用 ASP.NET 應用程序的所有功能。您必須知道這些功能,因為它們會在服務世界中導致意外的行為。主要功能之一是應用程序回收,包括應用程序域回收和進程回收。通過 IIS 管理控制台,可以在希望發生回收時配置不同的規則。可以為內存、時間和請求處理數量設置某些阈值,如圖 5-10 所示。當 IIS 回收工作進程時,還將回收工作進程中的所有應用程序域。通常,當基於 ASP.NET的Web 應用程序中的關鍵文件更改時,應用程序域也將回收。例如,在更改 Web.config文件或 Bin文件夾中的程序集時,將發生該操作。
圖 5-10:應用程序池回收設置
注意:此處描述的進程回收包括 Windows Server 2003中的回收。若要在Windows XP和IIS 5.1中啟用進程回收,可以從Microsoft 網站下載 IIS 5.0進程回收工具。進程回收工具作為服務在運行 IIS 5.0或IIS 5.1的計算機上運行。
修改 .svc文件之後,還將回收應用程序域。承載環境將嘗試按時正常關閉所有 WCF服務的打開連接。如果由於某種原因使服務無法按時關閉,系統將強制中止它們。通過 HostingEnvironmentSettings 配置設置,可以影響回收的行為,如列表 5-8 所示。idleTimeout 設置確定應用程序域在回收前的空閒時間長度(秒)。shutdowntimeout 設置確定正常關閉應用程序前的時間長度(秒)。發生此超時後,它將強制應用程序關閉。
列表 5-8:包含回收設置的hostingenvironment 節的Web.config
<system.web>
<hostingEnvironment idleTimeout="20"
shutdownTimeout="30"/>
</system.web>
使用 WCF 會話時,理解這些回收功能很重要。通常,在安全和可靠消息方案中有這種情況,本書的第 6 章和第 8 章將對此進行介紹。默認情況下,WCF 將會話狀態存儲在內存中。這是與 ASP.NET 會話狀態不同的實現,它沒有需要切換到持久會話狀態存儲的配置。但在安全和可靠消息方案中,您可以並且應當受益於 ASP.NET 實現。通過使用 WCF的ASP.NET 兼容性功能,可以獲得 ASP.NET 會話狀態的SQL Server 和狀態服務器實現,以支持企業可用的方案。在下一節中,將介紹如何受益於 WCF ASP.NET 兼容性模式。
ASP.NET 兼容性模型
如果在負載平衡或者甚至 Web 園的環境中承載 WCF服務,並且在該環境中後續的會話請求可以被此環境內的不同宿主或進程處理,則需要對會話狀態進行進程外持久存儲。最新的WCF 不支持會話狀態的持久存儲。相反,WCF 將它的所有會話狀態存儲在內存中。如果在IIS中承載 WCF服務,最後可以使用回收方案,上一節對此進行了描述。WCF 依賴於會話狀態的ASP.NET 實現,而不是為會話全部再次建立持久存儲。此方式有一個嚴重的限制:使服務僅限於 HTTP。
ASP.NET 會話狀態不是受 ASP.NET 兼容性模式支持的唯一功能。它還支持諸如 HttpContext、globalization 和模擬等功能,就像用於 ASP.NET Web服務 (ASMX) 一樣。有關啟用進程外會話狀態的特定於 ASP.NET的功能,請參考 MSDN 幫助。
若要查看 ASP.NET 兼容性模式的限制,必須用 AspNetCompatibilityRequirements 屬性顯式標記服務,如列表 5-9 所示。
列表 5-9:AspNetCompatibilityRequirements 屬性
namespace QuickReturns.StockTrading.ExchangeService
{
[ServiceBehavior(InstanceContextMode=InstanceContextMode.Single,
ReturnUnknownExceptionsAsFaults=true)]
[AspNetCompatibilityRequirements(
RequirementsMode=AspNetCompatibilityRequirementsMode.Allowed)]
public class TradeService : ITradeService
{
...
}
}
AspNetCompatibilityRequirementsMode 屬性有以下允許值。
表 5-1. AspNetCompatibilityRequirementsMode 屬性的值
值 說明 NotAllowed 指示服務可能“永遠不能”運行在ASP.NET 兼容性模式中。如果在方案中服務實現不能在ASP.NET 兼容性模式中工作(例如,在服務不是為 HTTP 生成的方案中),則必須設置此項。 Allowed 指示服務“可能”運行在ASP.NET 兼容性模式中。只有當您知道服務可能在此模式中工作時,才能選取此值。 Required 指示服務“必須”運行在ASP.NET 兼容性模式中。如果服務需要進行持久會話存儲,請選取此值。
選擇“Required”選項時,WCF 將驗證服務的所有受支持的端點都是 HTTP 端點,並且,如果它們不是,則會在ServiceHost 初始化期間產生異常。除了 AspNetCompatibilityRequirements 屬性以外,還必須設置 aspNetCompatibilityEnabled,如列表 5-10 所示。
列表 5-10:啟用了 ASP.NET 兼容性的配置
<?xml version="1.0"?>
<configuration
xmlns="http://schemas.microsoft.com/.NetConfiguration/v2.0">
<system.serviceModel>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true"/>
<services>
...
</services>
<behaviors>
...
</behaviors>
</system.serviceModel>
</configuration>
注意:本書附帶的示例代碼包含在ExchangeServiceInline.svc文件中承載的TradeService服務,它被配置為在ASP.NET 兼容性模式中運行。您可以在第 5 章的解決方案文件(請參考示例代碼下載鏈接)中找到它。
Windows XP和IIS 5.1
Windows 2000 附帶的IIS 5.0 拆分了 IIS進程模型,並引入了工作進程。此更改的主要原因是為了隔絕應用程序,以便 IIS 可以承載相互依賴較少的不同應用程序。IIS 5.0 與 Windows 2000 一起發布,而IIS 5.1 與 Windows XP 一起發布。WCF 不支持在帶 IIS 5.0的Windows 2000 上承載服務;因此,我們將只詳細考查 IIS 5.1。IIS 5.1 受支持,但它有僅一個站點的限制,並且每個應用程序都運行在一個稱為 aspnet_wp.exe的工作進程中。IIS 5.1對於開發 ASP.NET 網站和 WCF服務是很好的版本。它不是為企業使用而准備的,因為它有連接限制,並且只運行在早期的Windows 版本或 Windows XP的客戶端版本上。在本章中,我們將討論 IIS 5.1。
在圖 5-11中,可以看到 IIS 5.1的進程模型。體系結構被拆分成兩部分。左側的W3svc.exe 承載 HTTP 偵聽器、啟動工作進程並管理配置。另一側的工作進程則使 IIS 5.1 能夠承載托管的.NET 應用程序,在這裡,ASPNET_ISAPI.dll 負責創建托管 .NET 應用程序域。請注意,在Windows XP 上,W3svc.exe Windows服務與 SMTP和FTP服務一起承載在SvcHost.exe進程中。
圖 5-11:IIS 5.1進程模型體系結構
注意:不必有 IIS 即可運行 ASP.NET和WCF服務。例如,可以使用 Visual Studio 2005 附帶的ASP.NET 開發 Web服務器。在發布 Windows XP 時,Visual Studio 還沒有此功能。必須使用 IIS 5.1 才能在Windows XP 上開發 Web 應用程序。
Windows Server 2003和IIS 6.0
到 Windows Server 2003 時,Microsoft 引入了內核模式 HTTP 堆棧,稱為 HTTP.SYS。HTTP.SYS 通過 W3svc.exe 插入 IIS 6.0 體系結構中。W3svc.exe 是用戶模式組件,用於橋接內核模式的HTTP.SYS 實現,並將它連接到在IIS 5.1中已有的進程和配置管理系統。到 IIS 6.0 時,應用程序池的概念更加普及。盡管在IIS 5.1中只有托管 (ASP.NET) 應用程序可以承載在單獨的應用程序池中,但在IIS 6.0中所有類型的應用程序都可以承載在單獨的應用程序池中。ASPNET_ISAPI.dll 仍然負責啟動在托管 ASP.NET 世界中的應用程序域。圖 5-12 說明了 IIS 6.0中的進程模型。
圖 5-12:在IIS 6.0中承載的IIS 6.0進程模型體系結構
下面的詳細步驟說明如何在IIS 6.0中承載 .NET 3.0 WCF服務。我們將使用在前面描述的示例在IIS 6.0中進行承載。
1、請在示例代碼文件夾中打開包含 ExchangeServiceIISHost文件夾的文件夾。
2、下一步是在IIS中為該文件夾創建虛擬目錄。可以通過 IIS 管理器導航;但為簡單起見,只需右鍵單擊此文件夾,然後選擇“屬性”。
3、一旦出現屬性對話框,請單擊“Web 共享”選項卡。只需單擊“共享此文件夾”單選按鈕,將顯示“編輯別名”。將別名從“ExchangeServiceIISHost”重命名為“ExchangeService”。可以啟用“目錄浏覽”以使您更容易查看並單擊網站中的項目。通常,這是只用於開發的設置;關於 Web 共享設置,請參見圖 5-13。
警告:此設置允許用戶浏覽站點中的所有文件,就像使用 Windows 資源管理器一樣。雖然是好功能,但請在實際運行環境中使用時一定要小心。
圖 5-13:Web 共享“編輯別名”對話框
1、此時,只需單擊“確定”幾次,即可退出對話框。現在,應當可以通過以下網址 http://localhost/ExchangeService 訪問站點。但是,我們仍然必須檢查為此站點設置的ASP.NET的版本。如果只安裝了 .NET 2.0(就是說從未安裝 .NET 1.1),則應當不用做其他操作,但檢查一下是有好處的。因此,請打開 IIS 管理器(“開始” | “控制面板” | “管理工具” | “Internet 信息服務”)。一旦看到“屬性”對話框,請單擊“ASP.NET”選項卡,然後使用下拉框將 ASP.NET的版本切換到 .NET 3.0(受支持的版本)2.0.50727(RTM 版本)。
2、對於我們的示例,有一個額外的步驟,用於使“匿名”請求能夠訪問資源。匿名請求是指沒有與 HTTP 請求關聯的標識或 Windows 主體的任何請求。
單擊“目錄安全”選項卡,然後在對話框的“匿名訪問和身份驗證控制”區域下單擊“編輯”。確保選項“匿名訪問”被啟用。這將允許我們的示例運行,而不會涉及如何為請求提供身份驗證憑據。
此時,如果使用 Internet Explorer 浏覽到 http://localhost/ExchangeService 位置,將能夠看到一個目錄列表(只要設置與上一圖中相似)。如果單擊 Service.svc,將轉到由 *.svc 擴展的System.ServiceModel.Activiation.HttpHandler 生成的默認幫助屏幕。
此時,將執行與在客戶端應用程序中相同的步驟,要麼直接通過使用 Svcutil.exe 實用程序生成代理類,要麼右鍵單擊項目並通過“添加服務”加載項功能生成代理,本章後面的“使用 WCF服務”一節將對此進行介紹。
此示例附帶的解決方案有完整的控制台客戶端,它可以調用我們剛創建的WCF服務。
在IIS 7.0 上進行承載
IIS 7.0 推動了 Web服務器領域中的又一重大演進。可以在圖 5-14中看到兩個重要改變。第一,現在特定於協議的偵聽器適配器支持所有四種 WCF 傳輸,而不是僅限於 IIS 6.0中的HTTP 傳輸。此外,出現了稱為 Windows 激活服務 (WAS)的新操作系統服務。W3svc.exe和WAS 都運行在稱為 SvcHost.exe的操作系統宿主的內部。為了能夠將 IIS 6.0進程模型的強大功能與 WCF 結合使用,則需要進行這些更改。您可能會問“為什麼?”好的,WCF服務也工作在IIS 5.1和IIS 6.0中,那麼,通過在IIS中推廣進程模型和激活功能可以獲得什麼好處呢?很簡單:通過推廣激活概念使它與協議無關,而不是綁定到 HTTP,可以將平台的激活功能擴展到幾乎所有傳輸類型。
圖 5-14:IIS 7.0進程模型體系結構
在新發布的Windows Vista和Windows Server 2007中,Microsoft 轉移了 IIS的進程管理和配置功能,並使它在操作系統內部普遍可用。這使建立於該模型上的任何應用程序都能基於傳入的消息使用運行時激活和生成工作進程的功能。
HTTP、TCP/IP、命名管道和 MSMQ的特定於協議的偵聽器適配器運行於它們自己的進程內部,並將特定傳輸橋接到 WAS。偵聽器適配器要求 WAS 激活工作進程,然後將實際通信轉交給這些工作進程內部的特定協議處理程序。因此,WAS 現在擁有 W3svc.exe中具備的所有功能。通過將此責任拆分成多個單獨的進程,其他三種傳輸也受益於過去內置在IIS 6.0中但只用於 HTTP的進程模型和激活功能。總而言之,使用 IIS 7.0 可以跨越 IIS中提供的任何傳輸類型承載任何 WCF服務。在下一節中,將介紹 WAS 激活的工作原理,以及如果希望在Windows Vista或Windows Server 2007 上的IIS 7.0和WAS內部承載 WCF服務時必須注意的事項。
若要在IIS 7.0內部承載本書中使用的TradeService,您要做的就是配置 IIS,並將為 IIS 6.0 創建的.svc文件放在您將創建的站點中。利用以下步驟您將能夠在Windows Server 2007 上配置 IIS 7.0、WAS和.NET Framework 3.0,並使 TradeService 運行在IIS 7.0內部:
1、啟動服務器管理器(位於“管理工具”中)。
2、向服務器添加 Web服務器 (IIS) 角色。
3、注意,安裝 Web服務器時將自動添加 WAS。
4、在IIS的“詳細設置”屏幕上,選擇“ASP.NET”,並在“安全”下選擇“基本和 Windows 身份驗證”。讓其余選項保持默認設置。
這將安裝 IIS和WAS。
5、默認情況下,Windows Server 2007 不附帶安裝 .NET Framework 3.0。若要安裝 .NET Framework 3.0,請打開“添加功能向導”(“控制面板” | “程序” | “Windows 功能”)。
6、單擊“添加功能”,並選擇“NET Framework 3.0”(如果要用 WCF MSMQ 傳輸進行實驗)。還應選擇“MSMQ”。
現在,就可以准備在IIS 7.0 上運行 WCF服務了。下一步是在IIS中創建在其中運行服務的應用程序。這需要使用 Internet 信息服務 (IIS) 管理器。可以在“開始”菜單的“管理工具”中找到 IIS 管理工具。然後,導航到您的服務器和您的網站,最後找到默認網站。右鍵單擊默認網站,並選擇“創建應用程序”,如圖 5-15 所示。
圖 5-15:在IIS 管理器中新建應用程序
現在,需要指定本地計算機上的一個文件夾,用於承載應用程序的.svc文件。如圖 5-16 所示,可以為應用程序指定一個用於訪問服務的名稱 (http://localhost/<chosenname>) 和駐留文件的文件夾,然後選擇應用程序池。
圖 5-16:在IIS 管理器中為新應用程序設置屬性
如果正確完成所有操作,則可以通過 IIS 7.0 訪問您的服務。通過導航到新創建的應用程序可以測試實際效果,例如:
http://localhost:8080/QuickReturns/Exchange.svc/ExchangeService
Windows 激活服務
WAS 使您能夠承載任何 WCF服務,以便在IIS 模型內部支持任何傳輸。WAS 接管了最初 IIS 6.0中 W3svc.exe Windows服務的創建工作進程和提供配置的工作(並運行在Inetinfo.exe進程的內部)。WAS和IIS 現在共享用於定義站點、應用程序、應用程序池和虛擬目錄的配置存儲區。在這一節中,我們將介紹用 WAS 激活的過程,如圖 5-17 所示。
默認情況下,如果沒有向新啟動的服務器發出請求,Windows 將運行五個服務(如果啟用了所有協議)。下面是這些 Windows服務:
◆WAS
◆萬維網發布服務(承載偵聽器適配器)
◆NET.TCP 偵聽器適配器
◆NET.PIPE 偵聽器適配器
◆NET.MSMQ 偵聽器適配器
圖 5-17:用 WAS 為 HTTP 請求激活工作進程
偵聽器適配器啟動時,它們將向WAS進行注冊,並接收對應其特定協議的WAS/IIS 配置。由此,偵聽器適配器可以感知它們應當支持的站點和應用程序。然後,每個偵聽器適配器開始偵聽由配置提供的合適端口,這樣,它就可以將進入的請求分派給合適的應用程序。
一旦第一個請求進入,偵聽器適配器就將調用 WAS 以激活工作進程,其中包括作為請求目標的特定應用程序的托管 .NET 應用程序域。
然後,請求被遞交給工作進程內部的所謂應用程序域協議處理程序,以處理請求並將響應返回給客戶端。它不關心請求是 WCF服務請求、ASP.NET 請求還是對IIS 7.0的任何其他請求。創建激活進程是為了使工作進程能夠在請求到來時啟動。
為了在應用程序域內部啟動 WCF ServiceHost,應用程序域協議處理程序必須調用稱為 EnsureServiceAvailable的靜態方法。該方法與協議無關,並且將激活整個服務,包括所有端點和傳輸(而不僅是調用該方法的協議處理程序的傳輸)。
注意 在偵聽器適配器和協議處理程序的內部,尤其對於 HTTP和TCP 協議發生了一些不可思議的事情。在單獨進程中所承載的偵聽器適配器內部,套接字被打開。然後,當第一個請求到來時,實際上套接字將被從偵聽器適配器轉交給應用程序域協議處理程序,以便能夠處理第一個請求和任何後續請求!
承載方案
本章前一節介紹了用於承載服務的不同方案。此外,還介紹了哪種承載方案可以滿足哪些業務要求(或非功能性要求)。通常,可以采用“為什麼不是 IIS?”的方法。這是什麼意思呢?IIS 在功能方面提供了最佳選擇,尤其是在服務要公開多個系統所依賴的關鍵業務功能的情形下。如果選擇 IIS,就必須選擇使用 IIS 6.0 還是 IIS 7.0,由於新的激活功能,顯然應當選擇後者。在需要進程間通信的情形下,WinForms 和控制台應用程序都是可行方案。Windows服務本質上只是 IIS的替代方案,並且通常在建立服務器產品或需要對服務的激活和壽命期進行高級控制時使用它。
在下一節中,我們將介紹為使用服務而提供的選項,以及承載方案對使用者端意味著什麼。
使用 WCF服務
在前一節中,我們介紹了不同的承載方案。而所選的承載方案會影響使用者端。使用 WCF服務可以有多種方式。如果客戶端正在使用 WCF,則生產效率將非常高,因為 WCF 附帶的工具可以生成用於調用 WCF服務的代理類。WCF 主要通過 SvcUtil.exe 來提供標准和工具支持,SvcUtil.exe 將作為主要的元數據解釋工具。它與 WCF Framework 利用反射詢問具有合適屬性的類型這一功能結合在一起,使生成和使用 WCF Framework 與現有框架相比,復雜性更低。此外,Visual Studio 2005 帶有易用的功能,可以向項目添加服務引用,並可無縫地自動生成代理類。
實際上,您可以有以下選擇:
◆從服務檢索 WSDL,並手動制作代理來調用服務。這是客戶端沒有 WCF 時的典型方案。關於此方案,請參考第 13 章。
◆使用 Visual Studio 2005的“添加服務引用”功能,並讓它生成要在客戶端上使用的代理。
◆使用 SvcUtil.exe 工具生成代理類。
在下面幾節中,我們將介紹後面兩個選項:Visual Studio 2005和SvcUtil.exe。
服務代理
服務代理使您能夠以面向對象的方式使用服務。代理類對服務所使用的通信模型進行抽象,這樣,客戶端開發人員不會直接意識到他正在與(遠程)服務對話。這就像在調用本地代碼一樣。代理類可實現服務的服務接口,從而使您能夠調用服務接口上的方法,就好像它們是本地方法。代理是為服務接口中使用的任何自定義類型而生成的。列表 5-11 包含 QuickReturns Ltd. 示例中為 TradeService服務生成的代理的片段。它演示了在客戶端有一個可用 Quote 映射到服務器端上的Quote對象,盡管它們是不同的類。Quote對象按照合同進行序列化,以便它在服務端可以序列化為服務端版本的Quote 數據合同。此外,可以看到 GetQuote和PlaceQuote 方法調用一個基類,而該基類最後將以所配置的傳輸方式跨服務邊界進行調用。
列表 5-11:為 TradeService服務生成的示例代理
namespace SimpleClientWithProxy.ExchangeService
{
[DataContract()]
public partial class Quote : object, IExtensibleDataObject
{
// 省略了打印代碼中的Quote 數據成員,見示例代碼
}
}
[GeneratedCode("System.ServiceModel", "3.0.0.0")]
[ServiceContract()]
public interface ITradeService
{
[
OperationContract(Action =
"http://tempuri.org/ITradeService/GetQuote",
ReplyAction =
"http://tempuri.org/ITradeService/GetQuoteResponse")]
Quote GetQuote(string ticker);
[
OperationContract(Action =
"http://tempuri.org/ITradeService/PublishQuote",
ReplyAction =
"http://tempuri.org/ITradeService/PublishQuoteResponse")]
void PublishQuote(Quote quote);
}
[GeneratedCode("System.ServiceModel", "3.0.0.0")]
public interface ITradeServiceChannel : ITradeService, IClientChannel
{
}
[GeneratedCode("System.ServiceModel", "3.0.0.0")]
public partial class TradeServiceClient : ClientBase,
ITradeService
{
// 省略了打印代碼中的一些構造函數,見示例代碼
public SimpleClientWithProxy.ExchangeService.Quote
GetQuote(string ticker)
{
return base.Channel.GetQuote(ticker);
}
public void PublishQuote(
SimpleClientWithProxy.ExchangeService.Quote quote)
{
base.Channel.PublishQuote(quote);
}
}
使用 Visual Studio 2005
與創建 ASP.NET 代理相似,如果在IDE中右鍵單擊項目,可以看到三個用於添加引用的選項,如圖 5-18 所示。
圖 5-18:添加對WCF服務的引用
您要查找的選項是“添加服務引用”。此菜單選項是 SvcUtil.exe 實用程序周圍的包裝(下一節將對此進行介紹),它實際上將產生具有所需參數的進程。一旦選擇了“添加服務引用”,就將看到在圖 5-19中顯示的對話框。
圖 5-19:“添加服務引用”對話框
一旦在對話框中單擊“確定”,該加載項將產生 SvcUtil.exe,並生成需要的代理類和必需的配置文件(或修改它),並將所需引用添加到項目中。現在,項目的引用將列出 WCF 程序集。
注意 要使該操作有效,必須運行 Windows ServiceHost,或更改 URL 以指向IIS中承載的任何服務(使 URL 指向任何 .svc文件)。
現在,即可開始在服務層中安排第一個服務調用。示例解決方案文件按以下方式進行了修改,以幫助您查看代碼:
◆解決方案上的“設置啟動項目”已選中多個項目。
◆ExchangeServiceIISHost Web 項目的“使用動態端口”已設置為 False,並且“端口號”使用硬編碼設置。
需要將對象的簡短說明添加到項目中。在SvcUtil.exe(“添加服務引用”)調用期間,在項目中自動添加了下面的項和引用。其中一些只是為了幫助 Visual Studio 集成;其他則是通過代理直接使用服務所必需的。
◆服務引用:在此文件夾中,我們添加了兩項。第一,“映射”文件為通過 Visual Studio 加載項生成和重新生成代理提供支持。第二,ExchangeService.cs 代表具體的代理類實現,它利用命名空間 System.ServiceModel 提供簡單的集成類。
◆配置:第二項是 App.config文件。App.config文件(在Visual Studio 構建過程中將自動重命名為“<程序集名稱>.config”)提供運行時 WCF 配置參數。如果看一看此文件的內部,將發現大量設置,其中很多是默認的或多余的。常見做法是,在生成該文件後使用 WCF SvcConfigEditor.exe 編輯器實用程序管理該文件。此實用程序位於 Windows SDK Bin 目錄下。還可以在“Visual Studio 2005 工具”菜單中找到它。圖 5-20 顯示了該工具的實現。
圖 5-20:SvcConfigEditor.exe
從圖 5-20中的“SvcConfigEditor.exe”屏幕上可以看到,通過配置可以管理數量巨大的詳細屬性。這是 WCF的最強大的優勢之一:能夠對具體實現的很多方面進行控制,而不會影響核心服務實現。服務實現不需要更改即可從基於 HTTP的協議遷移到另一個面向消息的協議這一概念就是一個示例。若要獲得有關該工具的功能的詳細信息,請參考本書的第 3 章、第 6 章或 MSDN 幫助。
命令行實現
一種替代方法是直接利用 SvcUtil.exe 實用程序,而不是 Visual Studio 加載項。在從Visual Studio中直接執行時,Visual Studio 加載項將再次帶參數調用 SvcUtil.exe 以生成代理。通過查看“輸出”窗口,並在下拉列表中將“顯示輸出”設置為“服務引用”,可以看到命令行和該命令的結果。
若要手動生成,可通過選擇“開始” | “所有程序” | “Microsoft Windows SDK” | “CMD”,以選擇 CMD 窗口。此命令提示符很有用,因為它的路徑被設置為 SDK 工具和實用工具所在的二進制目錄。
您將使用 SvcUtil.exe 命令行工具生成可在SimpleClientWithProxy 項目中使用的兩個輸出。但是,本章附帶的示例代碼使用了上一節介紹的“添加服務引用”方法。此處介紹的步驟解釋了如何生成與“添加服務引用”相同的輸出。它生成的輸出文件是客戶端代理源代碼文件和應用程序配置文件。然後,這些文件將合並到客戶端項目中。SvcUtil.exe 可以生成這二者。在此示例中,以下命令(它只有一行,盡管此處顯示多行)將產生代理類和配置文件:
列表 5-12:用於產生代理類和配置文件的命令
svcutil /config:app.config /out:"ExchangeService.cs" /language:csharp
/n:*,
SimpleClientWithProxy.ExchangeService
"http://localhost/ExchangeService/?
ExchangeService.svc"
警告:要讓此操作有效,需要一個正在運行的Windows ServiceHost 版本,或者必須更改 URL 以指向IIS中承載的任何服務(使 URL 指向本章討論的任何 .svc文件)。此外,服務需要 metadataexchange 端點,第 3 章對此進行了介紹。本章附帶的代碼配置了 metadataexchange 端點,但在本章中它不在內嵌代碼內!
命令有很好的自解釋功能。/n 開關表明生成的代理類應當屬於哪個命名空間。最後一個參數是可以在其上找到架構信息的服務端點的URL。注意,?wsdl 可以替換為 ?mex,因為 SvcUtil.exe 同時支持兩種發現方法。通過從命令提示符執行 svcutil.exe /?,可以獲得進一步幫助。
下一步是獲得輸出文件 ExchangeService.cs和App.config,並將它們合並到項目中。通過從Visual Studio 2005中的“項目”菜單選擇“添加現有項”,可以將第一個文件 ExchangeService.cs 直接添加到項目中。
第二個文件必須作為應用程序配置 (App.config)文件添加到項目中。如果項目還沒有 App.config文件,則可以從“項目”菜單中再次選擇“添加現有項”以添加該文件。如果已有現成的App.config,則必須合並 system.serviceModel 部分,以確保具備所有適當的子元素。
結論
在了解了有關承載的可選方案的所有內容後,您將能夠構建 WCF 應用程序,並在任何需要的地方承載它們。此外,您還能夠解釋在最新可用環境(Windows Vista或Windows Server 2007 上的IIS 7.0 與 WAS)中進行承載的好處。
作者簡介
Chris Peiris 是應用程序集成方面的熱心作者。他在澳大利亞的Avanade 公司擔任解決方案設計師。他經常在有關 Microsoft 技術的專業開發人員會議上發言。Chris 為包括 15Seconds、ASPToday、Wrox (Apress)和Developer Exchange (DevX) 在內的各種在線刊物編寫了很多文章、評論和專欄。他還與他人共同編寫了很多有關 WCF、Web服務、UDDI、C#、IIS、Java 和安全方面的書籍。Chris 目前主要關注 WCF、WinFX、IBM Message Broker、BizTalk 和其他 EAI 實現。若要查看 Chris的完整作品列表和詳細聯系信息,請訪問 http://www.chrispeiris.com/。
Dennis Mulder 於 1997 年開始他的職業生涯,專注於 Microsoft 技術。在2004 年 8 月,他開始服務於 Avanade,這是一家 Microsoft和Accenture的合資公司。目前,他主要關注 Microsoft 平台的幾個領域,具體包括面向服務的領域、集成和軟件工廠。作為在荷蘭的顧問,Dennis 通過利用 Microsoft 平台的強大功能與企業客戶共同合作解決其問題。Dennis 經常在荷蘭 Microsoft 會議和用戶組中發言,在2006 年初,他就已經成為 INETA的發言人。可以通過 [email protected] 或他的博客 http://www.dennismulder.net/ 與 Dennis 聯系。
Avanade 是全球 IT 咨詢公司,致力於使用 Microsoft 平台幫助企業取得盈利增長。通過利用拓展 Microsoft 技術的成熟解決方案,Avanade 幫助企業增加收入、降低成本並對創新技術進行再投資,以獲得競爭優勢。我們的顧問通過匯聚我們全球雇員的洞察力、創新和才干,按照每個客戶的要求、時間線和預算提供服務。有關其他信息,可以訪問 http://www.avanade.com/。