在IIS上發布基於Windows Azure Service Bus的WCF服務


概要

隨着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


免責聲明!

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



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