共用方式為


MSMQ 啟用

MsmqActivation 範例示範如何在從消息佇列讀取的 Windows Process Activation Service (WAS) 中裝載應用程式。 此範例會使用 netMsmqBinding ,並且以 Two-Way 通訊 範例為基礎。 在此案例中,服務是 Web 裝載的應用程式,而用戶端是自我裝載,並輸出至主控台,以觀察已提交的採購單狀態。

備註

此範例的安裝程式和建置指示位於本主題結尾。

Windows Process Activation Service (WAS)是 Windows Server 2008 的新進程啟用機制,提供類似 IIS 的功能,這些功能先前僅適用於 HTTP 型應用程式給使用非 HTTP 通訊協定的應用程式。 Windows Communication Foundation (WCF) 會使用接聽程式配接器介面來傳達透過 WCF 所支援之非 HTTP 通訊協定所接收的啟用要求,例如 TCP、命名管道和 MSMQ。 透過非 HTTP 通訊協定接收要求的功能是由在 SMSvcHost.exe中執行的受管理 Windows 服務所裝載。

Net.Msmq 接聽程式配接器服務 (NetMsmqActivator) 會根據佇列中的訊息啟動佇列應用程式。

用戶端會從交易範圍內,將採購單傳送至服務。 服務會接收交易中的訂單,並加以處理。 服務接著會以訂單狀態回呼用戶端。 為了提供雙向通訊便利,客戶端和服務端都會使用佇列來加入採購單和跟蹤訂單狀態。

服務合約 IOrderProcessor 會定義使用佇列的單向服務作業。 服務作業會使用回復端點將訂單狀態傳送至用戶端。 回復端點的位址是佇列的 URI,用來將訂單狀態傳回用戶端。 訂單處理應用程式會實作此合約。

[ServiceContract(Namespace="http://Microsoft.ServiceModel.Samples")]
public interface IOrderProcessor
{
    [OperationContract(IsOneWay = true)]
    void SubmitPurchaseOrder(PurchaseOrder po,
                                           string reportOrderStatusTo);
}

傳送訂單狀態的回復協議是由客戶端所指定。 用戶端會實作訂單狀態合約。 服務會使用此合約產生的用戶端,將訂單狀態傳回用戶端。

[ServiceContract]
public interface IOrderStatus
{
    [OperationContract(IsOneWay = true)]
    void OrderStatus(string poNumber, string status);
}

服務作業會處理提交的採購單。 OperationBehaviorAttribute會套用至服務作業,以指定交易中的自動登記,以在服務作業完成時用來接收佇列的訊息,以及自動完成交易。 類別 Orders 會封裝訂單處理功能。 在此情況下,它會將採購單新增至字典。 服務作業所登記的交易可供 類別中的 Orders 作業使用。

除了處理提交的採購單之外,服務作業也會回復給客戶端有關訂單狀態的資訊。

public class OrderProcessorService : IOrderProcessor
{
    [OperationBehavior(TransactionScopeRequired = true, TransactionAutoComplete = true)]
    public void SubmitPurchaseOrder(PurchaseOrder po, string reportOrderStatusTo)
    {
        Orders.Add(po);
        Console.WriteLine("Processing {0} ", po);
        Console.WriteLine("Sending back order status information");
        NetMsmqBinding msmqCallbackBinding = new NetMsmqBinding();
        msmqCallbackBinding.Security.Mode = NetMsmqSecurityMode.None;
        OrderStatusClient client = new OrderStatusClient(msmqCallbackBinding, new EndpointAddress(reportOrderStatusTo));
        // please note that the same transaction that is used to dequeue purchase order is used
        // to send back order status
        using (TransactionScope scope = new TransactionScope(TransactionScopeOption.Required))
        {
            client.OrderStatus(po.PONumber, po.Status);
            scope.Complete();
        }
    }
}

要使用的用戶端系結是使用組態檔來指定。

MSMQ 佇列名稱是在組態檔的 appSettings 區段中指定。 服務的端點定義於組態檔的 System.serviceModel 區段中。

備註

MSMQ 佇列名稱和端點位址會使用稍微不同的尋址慣例。 MSMQ 佇列名稱使用點(.)來代表本機計算機,並在路徑中使用反斜杠作為分隔符。 WCF 端點地址指定使用 net.msmq 協議,以 "localhost" 作為本機計算機的主機名稱,並使用正斜線來表示路徑。 若要從遠端電腦上裝載的佇列讀取,請將 “.” 和 “localhost” 取代為遠端電腦名稱。

具有類別名稱的 .svc 檔案會用來在 WAS 中裝載服務程序代碼。

Service.svc 檔案本身包含用於建立OrderProcessorService的指示詞。

<%@ServiceHost language="c#" Debug="true" Service="Microsoft.ServiceModel.Samples.OrderProcessorService"%>

Service.svc 檔案中也包含元件指示器,以便確保 System.Transactions.dll 被載入。

<%@Assembly name="System.Transactions, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"%>

用戶端會建立交易範圍。 在交易範圍內與服務進行通訊,使其被視為一個原子單位,其中所有訊息都必須同步成功或失敗。 交易會藉由在交易範圍上呼叫 Complete 來認可。

using (ServiceHost serviceHost = new ServiceHost(typeof(OrderStatusService)))
{
    // Open the ServiceHostBase to create listeners and start listening
    // for order status messages.
    serviceHost.Open();

    // Create a proxy with given client endpoint configuration
    OrderProcessorClient client = new OrderProcessorClient();

    // Create the purchase order
    PurchaseOrder po = new PurchaseOrder();
    po.CustomerId = "somecustomer.com";
    po.PONumber = Guid.NewGuid().ToString();

    PurchaseOrderLineItem lineItem1 = new PurchaseOrderLineItem();
    lineItem1.ProductId = "Blue Widget";
    lineItem1.Quantity = 54;
    lineItem1.UnitCost = 29.99F;

    PurchaseOrderLineItem lineItem2 = new PurchaseOrderLineItem();
    lineItem2.ProductId = "Red Widget";
    lineItem2.Quantity = 890;
    lineItem2.UnitCost = 45.89F;

    po.orderLineItems = new PurchaseOrderLineItem[2];
    po.orderLineItems[0] = lineItem1;
    po.orderLineItems[1] = lineItem2;

    //Create a transaction scope.
    using (TransactionScope scope = new
        TransactionScope(TransactionScopeOption.Required))
    {
        // Make a queued call to submit the purchase order
        client.SubmitPurchaseOrder(po,
       "net.msmq://localhost/private/ServiceModelSamplesOrder/OrderStatus");
        // Complete the transaction.
        scope.Complete();
    }

    //Closing the client gracefully closes the connection and cleans up
    //resources
    client.Close();

    Console.WriteLine();
    Console.WriteLine("Press <ENTER> to terminate client.");
    Console.ReadLine();

    // Close the ServiceHostBase to shutdown the service.
    serviceHost.Close();
    }

用戶端程式代碼會實作 IOrderStatus 合約,以從服務接收訂單狀態。 在此情況下,它會列印訂單狀態。

[ServiceBehavior]
public class OrderStatusService : IOrderStatus
{
    [OperationBehavior(TransactionAutoComplete = true,
                        TransactionScopeRequired = true)]
    public void OrderStatus(string poNumber, string status)
    {
        Console.WriteLine("Status of order {0}:{1} ",
                                         poNumber , status);
    }
}

順序狀態佇列是在 方法中 Main 建立的。 用戶端組態包含用來裝載訂單狀態服務的訂單狀態服務組態,如下列範例組態所示。

<appSettings>
    <!-- use appSetting to configure MSMQ queue name -->
    <add key="targetQueueName" value=".\private$\ServiceModelSamples/service.svc" />
    <add key="responseQueueName" value=".\private$\ServiceModelSamples/OrderStatus" />
  </appSettings>

<system.serviceModel>

    <services>
      <service
         name="Microsoft.ServiceModel.Samples.OrderStatusService">
        <!-- Define NetMsmqEndpoint -->
        <endpoint address="net.msmq://localhost/private/ServiceModelSamples/OrderStatus"
                  binding="netMsmqBinding"
                  contract="Microsoft.ServiceModel.Samples.IOrderStatus" />
      </service>
    </services>

    <client>
      <!-- Define NetMsmqEndpoint -->
      <endpoint name="OrderProcessorEndpoint"
                address="net.msmq://localhost/private/ServiceModelSamples/service.svc"
                binding="netMsmqBinding"
                contract="Microsoft.ServiceModel.Samples.IOrderProcessor" />
    </client>

  </system.serviceModel>

當您執行範例時,用戶端和服務活動會顯示在伺服器和用戶端控制台視窗中。 您可以看到伺服器從用戶端接收訊息。 在每個主控台視窗中按 ENTER 鍵,以關閉伺服器和用戶端。

用戶端會顯示伺服器所傳送的順序狀態資訊:

Press <ENTER> to terminate client.
Status of order 70cf9d63-3dfa-4e69-81c2-23aa4478ebed :Pending

要設定、建置和執行範例,請執行以下步驟:

  1. 確定已安裝 IIS 7.0,因為需要 WAS 啟用。

  2. 請確定您已針對 Windows Communication Foundation 範例 執行One-Time 安裝程式。 此外,您必須安裝 WCF 非 HTTP 啟用元件:

    1. 從 [ 開始] 功能表中,選擇 [控制面板]。

    2. 選取 [程式和功能]。

    3. 按兩下 [開啟或關閉 Windows 功能]。

    4. [功能摘要] 底下,按兩下 [新增功能]。

    5. 展開 Microsoft .NET Framework 3.0 節點,並檢查 Windows Communication Foundation 非 HTTP 啟用 功能。

  3. 若要建置解決方案的 C# 或 Visual Basic .NET 版本,請遵循建置 Windows Communication Foundation 範例 中的指示。

  4. 從命令視窗執行 client.exe 來執行用戶端。 這會建立佇列,並將訊息傳送到佇列。 讓用戶端保持執行狀態,以查看讀取訊息的服務結果

  5. MSMQ 啟用服務預設會以網路服務的形式執行。 因此,用來啟動應用程式的佇列必須具有網路服務的接收和查看許可權。 這可以使用消息佇列 MMC 來新增:

    1. 從 [ 開始] 功能表中,按兩下 [ 執行],然後輸入 Compmgmt.msc 並按 ENTER。

    2. [服務和應用程式] 底下,展開 [消息佇列]。

    3. 按兩下 [私人佇列]。

    4. 以滑鼠右鍵按兩下佇列(servicemodelsamples/Service.svc),然後選擇 [ 屬性]。

    5. 在 [ 安全性] 索引標籤上,按兩下 [ 新增 ],並授與查看和接收網路服務的許可權。

  6. 設定 Windows Process Activation Service (WAS) 以支援 MSMQ 啟用。

    為了方便起見,下列步驟會在位於範例目錄中AddMsmqSiteBinding.cmd的批處理檔中實作。

    1. 若要支持 net.msmq 啟用,默認網站必須先系結至 net.msmq 通訊協定。 這可以使用安裝於 IIS 7.0 管理工具組的 appcmd.exe來完成。 從具有提升許可權的命令提示字元(系統管理員)中,執行下列命令。

      %windir%\system32\inetsrv\appcmd.exe set site "Default Web Site"
      -+bindings.[protocol='net.msmq',bindingInformation='localhost']
      

      備註

      此命令是單行文字。

      此命令會將 net.msmq 網站系結新增至默認網站。

    2. 雖然網站中的所有應用程式都會共用一般 net.msmq 系結,但每個應用程式都可以個別啟用 net.msmq 支援。 若要啟用 /servicemodelsamples 應用程式的 net.msmq,請在具有管理員權限的命令提示字元中執行下列命令。

      %windir%\system32\inetsrv\appcmd.exe set app "Default Web Site/servicemodelsamples" /enabledProtocols:http,net.msmq
      

      備註

      此命令是單行文字。

      此命令可讓 /servicemodelsamples 應用程式使用 http://localhost/servicemodelsamplesnet.msmq://localhost/servicemodelsamples來存取。

  7. 如果您先前未這麼做,請確定 MSMQ 啟用服務已啟用。 從 [ 開始] 選單中,按下 [ 執行],然後輸入 Services.msc。 搜尋 Net.Msmq 接聽程式配接器的服務清單。 按一下滑鼠右鍵,然後選取 [屬性]。 將 [ 啟動類型 ] 設定為 [ 自動],按兩下 [ 套用 ],然後按下 [ 開始] 按鈕。 此步驟只能在 Net.Msmq 接聽程式配接器服務的第一次使用之前完成一次。

  8. 若要在單一或跨計算機組態中執行範例,請遵循 執行 Windows Communication Foundation 範例中的指示。 此外,變更提交採購單的用戶端程序代碼,以在提交採購單時反映佇列 URI 中的電腦名稱。 使用下列程式碼:

    client.SubmitPurchaseOrder(po, "net.msmq://localhost/private/ServiceModelSamples/OrderStatus");
    
  9. 拿掉您為此範例新增的 net.msmq 網站系結。

    為了方便起見,下列步驟會在名為 RemoveMsmqSiteBinding.cmd 的批處理檔中實作,其位於範例目錄中:

    1. 從啟用的通訊協定清單中移除 net.msmq,方法是從提升許可權的命令提示字元執行下列命令。

      %windir%\system32\inetsrv\appcmd.exe set app "Default Web Site/servicemodelsamples" /enabledProtocols:http
      

      備註

      此命令是單行文字。

    2. 從具有管理員權限的命令列執行下列命令,以移除 net.msmq 站台繫結。

      %windir%\system32\inetsrv\appcmd.exe set site "Default Web Site" --bindings.[protocol='net.msmq',bindingInformation='localhost']
      

      備註

      此命令是單行文字。

    警告

    執行批處理檔會將 DefaultAppPool 重設為以 .NET Framework 版本 2.0 執行。

根據預設, netMsmqBinding 系結傳輸會啟用安全性。 兩個屬性 MsmqAuthenticationModeMsmqProtectionLevel,一起決定傳輸安全性的類型。 根據預設,驗證模式會設定為 Windows ,而保護層級會設定為 Sign。 若要讓 MSMQ 提供驗證和簽署功能,它必須是網域的一部分。 如果您在不屬於網域的計算機上執行此範例,就會收到下列錯誤:「用戶的內部消息佇列憑證不存在」。

若要在加入工作組的電腦上執行範例

  1. 如果您的計算機不是網域的一部分,請將驗證模式和保護層級設定為 none 來關閉傳輸安全性,如下列範例組態所示。

    <bindings>
        <netMsmqBinding>
            <binding configurationName="TransactedBinding">
                <security mode="None"/>
            </binding>
        </netMsmqBinding>
    </bindings>
    
  2. 在執行範例之前,請先變更伺服器和用戶端上的組態。

    備註

    security mode 的設定改為 None 相當於將 MsmqAuthenticationModeMsmqProtectionLevelMessage的安全性設定為 None

  3. 若要在加入工作群組的計算機中啟用激活功能,啟用服務和工人進程必須使用特定使用者帳戶執行(兩者必須使用相同的帳戶),佇列必須為此特定使用者帳戶設定 ACL。

    若要變更工作進程執行時的身分識別:

    1. 執行 Inetmgr.exe。

    2. [應用程式集區] 底下,以滑鼠右鍵按兩下 AppPool (通常是 DefaultAppPool),然後選擇 [ 設定應用程式集區預設值...]。

    3. 變更 Identity 屬性以使用特定的用戶帳戶。

    若要變更啟動服務執行所在的身分識別:

    1. 執行 Services.msc。

    2. 以滑鼠右鍵按下 Net.MsmqListener 配接器,然後選擇 [ 屬性]。

  4. [LogOn] 索引標籤中變更帳戶。

  5. 在工作組中,服務也必須使用不受限制的令牌來執行。 若要這樣做,請在命令視窗中執行下列命令:

    sc sidtype netmsmqactivator unrestricted
    

另請參閱