概要
隨着Windows Azure在中國的落地, 相信越來越多的人會用到Windows Azure。Windows Azure提供了豐富的基於雲的各種服務,其中包括Service Bus(服務總線),通過Service Bus, 我們可以將傳統的WCF Service注冊到Window Azure Service Bus上。本文以IIS8, WCF4.0為例,詳細介紹如何將部署在IIS里面的WCF服務如何主動注冊到Windows Azure Service Bus。
注冊到Windows Azure Service Bus上的WCF服務, 其在運行時候的架構如下,
傳統的WCF服務有多種方式來進行HOST,比如self-hosted 或者IIS。如果通過self-hosted的方式的話, 只需要在開啟HOST的時候主動注冊到Windows Azure Service Bus即可。
如果WCF通過IIS的方式來Host,WAS會依據進來的請求來激活w3wp.exe進程。如果沒有沒有請求進入到web server的話,WCF不會主動注冊到Windows Azure Service Bus的。 這樣就存在一個問題:如果客戶端第一次去調用該Windows Azure Service Bus Endpoint的時候, 但是由於服務端WCF服務根本沒有注冊到Windows Azure Service Bus, 那么就會收到“No service is hosted at the specified address.”的異常. 因此將部署在IIS里面的WCF服務注冊到Windows Azure Service Bus上需要經過一些特殊的處理。
前提條件
1. 開發工具: Visual Studio 2012 + Windows Azure SDK2.0
2. 一個注冊好的Windows Azure 賬號
3. Windows Server 2012或者Windows 8
4. IIS8
實施步驟
1.首先我們需要在Windows Azure 里面創建一個Service Bus的namespace. 比如, 我創建了一個叫做IISSBWCF的namespace, 其會自動生成一個相應令牌:
2. 准備好Service Bus的訪問令牌之后, 下面我們就需要創建一個WCF服務, 並將該WCF服務注冊到該Windows Azure Service Bus上。
1) 打開VS2012, 創建一個WCF service application, 在該工程中, 我們需要引用ServiceBus相關Assembly。 我們可以通過點擊”References” ,右擊 選擇”Manage NuGet Packages…”, ,然后在線搜索”Windows Azure Service Bus”, 找到后安裝即可, 如下所示:
2) WCF Contract的定義和服務的實現和傳統WCF服務沒有任何區別。接下來是要把該WCF服務注冊到Windows Azure Service Bus上了。 下面的配置演示了通過配置的方式注冊到Windows Azure Service Bus:
“<?xml version="1.0" encoding="utf-8"?> <configuration> <system.web> <compilation debug="true" targetFramework="4.0" /> </system.web> <appSettings> <add key="EnableAutoStart" value="true"/> <add key="ActivatedURL" value="/iis-hosted-sb-wcf/Service1.svc"/> </appSettings> <system.serviceModel> <services> <service name="IIS_Hosted_SB.Service1"> <endpoint address="https://iissbwcf.servicebus.windows.net" binding="basicHttpRelayBinding" contract="IIS_Hosted_SB.IService1" behaviorConfiguration="sbTokenProvider"/> </service> </services> <behaviors> <endpointBehaviors> <behavior name="sbTokenProvider"> <transportClientEndpointBehavior> <tokenProvider> <sharedSecret issuerName="owner" issuerSecret="這里是我的Access Token,做替換處理” /> </tokenProvider> </transportClientEndpointBehavior> </behavior> </endpointBehaviors> <serviceBehaviors> </serviceBehaviors> </behaviors> <serviceHostingEnvironment multipleSiteBindingsEnabled="false" /> <extensions> <!-- In this extension section we are introducing all known service bus extensions. User can remove the ones they don't need. --> <behaviorExtensions> <add name="transportClientEndpointBehavior" type="Microsoft.ServiceBus.Configuration.TransportClientEndpointBehaviorElement, Microsoft.ServiceBus, Culture=neutral, PublicKeyToken=31bf3856ad364e35" /> </bindingElementExtensions> <bindingExtensions> <add name="basicHttpRelayBinding" type="Microsoft.ServiceBus.Configuration.BasicHttpRelayBindingCollectionElement, Microsoft.ServiceBus, Culture=neutral, PublicKeyToken=31bf3856ad364e35" /> </bindingExtensions> </extensions> </system.serviceModel> </configuration>
3) 當我們通過IIS第一次browse這個svc文件的時候, 那么其會自動注冊到Windows Azure Service Bus上。注冊成功后, 我們在Windows Azure 服務總線的管理台里面,也可以看到起處理活動的狀態,如下:
3. 現在問題是: 如果我們沒有主動去訪問svc文件來激活該WCF服務的話,那么客戶端在通過Windows Azure Service Bus去調用這個WCF服務的時候, 就會遇到如下異常,
4. 從IIS8開始(IIS7.5通過extension的方式來實現),我們提供了預熱功能,即使沒有請求進來, 我們也可以采用preload的方式完成初始化的工作,激活相關服務。而我們的WCF服務正好需要利用這一點。
實施步驟如下:
1) 首先需要將WCF服務所運行的Application pool設置為AlwaysRunning.
2) 然后實現IProcessHostPreloadClient接口的Preload方法:在里面實現對svc服務的激活。示例代碼如下:
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Threading; using System.ServiceModel.Activation; using System.ServiceModel; namespace IIS_Hosted_SB { public class AutoStartService:System.Web.Hosting.IProcessHostPreloadClient { public void Preload(string[] parameters) { bool isServceActivated = false; int attempts = 0; while (!isServceActivated && (attempts < 10)) { Thread.Sleep(1 * 1000); try { string ActivatedURL = System.Configuration.ConfigurationManager.AppSettings["ActivatedURL"].ToString(); ServiceHostingEnvironment.EnsureServiceAvailable(ActivatedURL); WriteTrace(“Windows Azure Service Bus Endpoint is activated”); isServceActivated = true; } catch (Exception exception) { attempts++; //continue on these exceptions, otherwise fail fast if (exception is EndpointNotFoundException || exception is ServiceActivationException || exception is ArgumentException) { //log } else { throw; } } } } } }
3) 修改IIS配置文件(%windir%\system32\inetsrv\config\applicationhost.config), 將剛才的自動激活服務Provider應用到該WCF服務的VD上。修改后的配置文件如下:
<sites> <site name="Default Web Site" id="1"> <application path="/"> <virtualDirectory path="/" physicalPath="%SystemDrive%\inetpub\wwwroot" /> </application> <application path="/iis-hosted-sb-wcf" applicationPool="DefaultAppPool" serviceAutoStartEnabled="true" serviceAutoStartProvider="AutoStartProvider"> <virtualDirectory path="/" physicalPath="C:\inetpub\wwwroot\iis-hosted-sb-wcf" /> </application> <bindings> <binding protocol="http" bindingInformation="*:80:" /> <binding protocol="net.tcp" bindingInformation="808:*" /> <binding protocol="net.msmq" bindingInformation="localhost" /> <binding protocol="msmq.formatname" bindingInformation="localhost" /> <binding protocol="net.pipe" bindingInformation="*" /> </bindings> <traceFailedRequestsLogging enabled="true" /> </site> … <serviceAutoStartProviders> <add name="AutoStartProvider" type="IIS_Hosted_SB.AutoStartService,IIS_Hosted_SB" /> </serviceAutoStartProviders> </system.applicationHost>
4) 經過以上這些配置后, 我們可以發現只要一旦該application pool被回收之后,馬上會有一個新的w3wp.exe被自動激活,同時其會自動注冊到Windows Azure Service Bus上。 任何時候客戶端通過Windows Azure Service Bus訪問該WCF service,我們都可以得到正確的響應, 如下所示:
參考文檔
How to Use the Service Bus Relay Service
http://www.windowsazure.com/en-us/develop/net/how-to-guides/service-bus-relay/
IIS hosting of Wcf Services with Servicebus Endpoints
http://archive.msdn.microsoft.com/ServiceBusDublinIIS/Release/ProjectReleases.aspx?ReleaseId=4336
Application Initialization Part 2
http://blogs.iis.net/wadeh/archive/2012/05/01/application-initialization-part-2.aspx
希望以上內容對您有所幫助
Winston He