WCF分散式開發步步為贏(13):WCF服務離線操作與訊息佇列MSMQ

技術小胖子發表於2017-11-11
   之前曾經寫過一個關於MSMQ訊息佇列的文章:WCF分散式開發必備知識(1):MSMQ訊息佇列 ,當時的目的也是用它來作為學習WCF 訊息佇列MSMQ程式設計的基礎文章。在那篇文章裡,我們詳細介紹了MSMQ訊息佇列的基本概念、安裝、部署、開發、除錯等相關問題。今天我們來學習WCF分散式開發步步為贏(13):WCF服務離線操作與訊息佇列MSMQ。在WCF框架下使用MSMQ訊息佇列服務程式設計。  這裡我會給出一個使用WCF MSMQ實現離線請求的DEMO示例程式。
    全文結構是:【1】MSMQ基本概念【2】WCF訊息佇列MSMQ的優勢【3】WCF 訊息佇列MSMQ通訊框架【4】安裝配置注意事項【5】示例程式碼 【總結】
 【1】MSMQ基本概念:
簡要回顧一下MSMQ的基本概念,詳細的你們可以參考WCF分散式開發必備知識(1):MSMQ訊息佇列
    MSMQ全稱MicroSoft Message Queue,微軟訊息佇列,是在多個不同的應用之間實現相互通訊的一種非同步傳輸模式,相互通訊的應用可以分佈於同一臺機器上,也可以分佈於相連的網路空間中的任一位置。它的實現原理是:訊息的傳送者把自己想要傳送的資訊放入一個容器中(我們稱之為Message),然後把它儲存至一個系統公用空間的訊息佇列(Message Queue)中;本地或者是異地的訊息接收程式再從該佇列中取出發給它的訊息進行處理。
【2】WCF訊息佇列MSMQ的優勢:
      訊息佇列MSMQ的優點:穩定、訊息優先順序、離線能力以及安全性,有保障的訊息傳遞和執行許多業務處理的可靠的防故障機制。 因此訊息佇列是實現SOA面向服務架構的重要元件之一。WCF框架提供了和MSMQ整合與擴充套件的能力。這一點也是WCF在特性中明確指出的。MSMQ支援離線訊息模式,而且在WCF框架下,提供了基於http橋的internet網路佇列服務的呼叫擴充套件。和MSMQ框架的結合和擴充套件,使得WCF服務具有的新的特點:
【2.1】Availabiliy:可用性。這個是MSMQ離線訊息的一種體現。客戶單和服務端不需要實時進行連線,然後進行訊息的互動.WCF 客戶端可以傳送請求到離線服務端,服務上線以後在相應客戶端請求。
【2.2】Disjoint:分解。可以講工作分解為多個操作,一次放入佇列。改善系統的可用性和吞吐量。
【2.3】Compensating:補償。對於多業務事務,可以提供單獨的事物提供其它事務失敗的善後處理。
【2.4】Load Leveling:負載平衡。可以把過載的客戶端請求放入佇列,空閒的時候進行處理,平衡系統的吞吐量,改善效能。
【3】WCF 訊息佇列MSMQ通訊框架:
       WCF使用NetMsmqBinding來支援訊息佇列通訊。當客戶端呼叫服務時,客戶端訊息會被封裝為MSMQ訊息,傳送懂到特定的訊息佇列。服務端宿主在執行轉檯下會,啟動通道偵聽器,來檢測訊息佇列訊息,如果發現對應的訊息,會從佇列裡取出訊息,使用分發器轉發給對應的服務。具體的通訊架構如圖:
    如果宿主離線,訊息會被放入佇列,等待下一次宿主聯機時,在執行訊息分發處理,給指定的WCF服務。
【4】安裝配置注意事項:
    MSMQ佇列幾種常見的型別就是:
1.公共佇列:在整個訊息佇列網路中複製,並且有可能由網路連線的所有站點訪問。 

2.專用佇列:不在整個網路中釋出。相反,它們僅在所駐留的本地計算機上可用。專用佇列只能由知道佇列的完整路徑名或標籤的應用程式訪問。 

3.管理佇列:包含確認在給定“訊息佇列”網路中傳送的訊息回執的訊息。指定希望 MessageQueue 元件使用的管理佇列(如果有的話)。 

4.響應佇列:包含目標應用程式接收到訊息時返回給傳送應用程式的響應訊息。指定希望 MessageQueue 元件使用的響應佇列(如果有的話)。
   這裡有幾個問題要注意,以前很多人也在配置MSMQ開發環境的時候遇到這個問題。Xp環境下作MSMQ配置開發有很多限制。這裡算是做個總結供大家參考:
1.公共佇列需要域控制器DC Domain Controller; 

2.私有佇列與託管的機器同屬本地,不需要DC,成為工作組安裝; 

3.私有佇列需要禁用安全模式:工作組安裝與安全,安全設定需要客戶端提供證書,MSMQ傳輸安全需要使用Windows安全,這裡需要使用AD活動目錄。
【5】示例程式碼 :
    今天的示例DEMO程式程式碼,主要演示的是WCF如何配置和開發一個MSMQ服務程式,實現WCF離線操作,MSMQ事務的部分由於內容較多,這裡暫時不涉及。我們只討論WCF離線操作。
(1)WCF服務程式碼:
    值得注意的WCF的操作要被定義為單向操作,因為本質上其符合單向操作的特徵。非同步,離線。無返回值。配置操作契約的時候要新增IsOneWay屬性。程式碼如下:
 //1.服務契約
    [ServiceContract(Namespace = http://www.cnblogs.com/frank_xl/)]

    
public interface IWCFMSMQService

    {

        
//操作契約,必須為單向操作
        [OperationContract(IsOneWay = true)]

        
void SayHelloMSMQ(string name);


    }

    
//2.服務類,繼承介面。實現服務契約定義的操作
    public class WCFMSMQService : IWCFMSMQService

    {

        
public WCFMSMQService()

        {

            Console.WriteLine(
WCF MSMQ Service instance was created at:{0},  DateTime.Now);

        }

        
//實現介面定義的方法
        public void SayHelloMSMQ(string name)

        {

            Console.WriteLine(
Hello! {0},Calling WCF MSMQ Service Operation at:{1}, name,DateTime.Now);

            

        }

    }
(2)宿主:
    我的開發環境為XP專業版,工作組模式。這裡有個問題要注意,就是安全。MSMQ預設的安全模式是需要證書支援。我們必須在宿主配置檔案裡給配置為none,簡化操作,因為證書需要MSMQ域管理器。MSMQ傳輸安全需要Windows安全,這個又需要AD活動目錄支援,工作組模式下不支援,因此這裡我們都設定為none。程式碼如下:
 
<services>

      
<service behaviorConfiguration=WCFService.WCFServiceBehavior

        name
=WCFService.WCFMSMQService>

        
<endpoint  

          address
=net.msmq://localhost/Private/FrankWCFMSMQ 

          binding
=netMsmqBinding         

          contract
=WCFService.IWCFMSMQService bindingConfiguration=msmq >

        
</endpoint>

       

        
<endpoint address=mex binding=mexHttpBinding contract=IMetadataExchange />

        
<host>

          
<baseAddresses>

            
<add baseAddress=http://localhost:8001//>

          
</baseAddresses>

        
</host>

      
</service>

    
</services>

    
<behaviors>

      
<serviceBehaviors>

        
<behavior name=WCFService.WCFServiceBehavior>

          
<serviceMetadata httpGetEnabled=true />

          
<serviceDebug includeExceptionDetailInFaults=false />

        
</behavior>

      

      
</serviceBehaviors>

    
</behaviors>

    
<bindings>

      
<netMsmqBinding>

        
<binding name=msmq durable=false exactlyOnce=false>

          
<security mode=None>

            
<transport msmqProtectionLevel=None/>

            
<message clientCredentialType=None/>

          
</security>

        
</binding>

      
</netMsmqBinding>

    
</bindings>
(3)客戶端:
    執行客戶端,新增服務引用,這裡客戶端的配置檔案要做修改,安全模式也修改和宿主對應,設定為none。客戶端測試方案是每個2秒呼叫一次服務請求。我們這裡在宿主端列印了時間。客戶端傳送訊息完畢以後,宿主暫時不啟動。等待一段時間。在啟動宿主,觀察宿主列印的訊息。程式碼如下:
 
            //HTTP NetMsmqBinding_IWCFMSMQService
            WCFMSMQServiceClient wcfServiceProxy = new WCFMSMQServiceClient(NetMsmqBinding_IWCFMSMQService);

            
//通過代理呼叫SayHello服務,這裡及時服務呼叫服務失敗,訊息會傳送到佇列裡進行快取。
            Console.WriteLine(WCF First Call at:{0},DateTime.Now);

            wcfServiceProxy.SayHelloMSMQ(
Frank);

            Thread.Sleep(
2000);//客戶端休眠兩秒,繼續下一次呼叫
            Console.WriteLine(WCF Second Call at:{0}, DateTime.Now);

            wcfServiceProxy.SayHelloMSMQ(
Frank Xu);

            Thread.Sleep(
2000);//客戶端休眠兩秒,繼續下一次呼叫
            Console.WriteLine(WCF Last Call at:{0}, DateTime.Now);

            wcfServiceProxy.SayHelloMSMQ(
Frank Xu Lei);
(4)執行結果:
   首先是客戶端傳送到的訊息,我們可以再計算機-管理-服務-專用佇列裡檢視到,如
    以前的服務要求我們必須啟動宿主,不然會出現連線錯誤。這裡為了測試,停留約4分鐘後,我們啟動宿主。觀察宿主列印的訊息:
    宿主在聯機以後響應了客戶端的呼叫操作。
【總結】
     本節文章主要講解的是WCF 如何使用MSMQ開發離線服務操作。這裡除了回顧了MSMQ的基本概念,還介紹了WCF服務使用MSMQ的通訊框架的優勢和特點。最後給出了基於WCF 訊息佇列的離線服務呼叫實現的過程。
    WCF 對MSMQ訊息佇列的支援和擴充套件,大大提高了WCF服務呼叫的伸縮性和靈活性。本文由於開發環境的關係,沒有給出公共佇列的開發實現過程。另外在WCF 訊息佇列開發過程中,大家要做注意。
(1)在服務宿主端啟動宿主,要做佇列存在的判斷,以免出現讀取錯誤。
(2)佇列服務涉及到安全的問題,認證和訊息加密,簽名,需要證書的配置。條件限制這裡就沒有給出具體的實現過程。
(3)WCF佇列服務的另外一個重要概念就是對離線事務的支援。這一特性會在後續文章裡給出。
(4)執行環境:Xp pro,.net 3.0以上,vs2008,至少安裝MSMQ佇列的私有佇列元件服務。
     最後給出本文的參考程式碼:/Files/frank_xl/WCCFServiceMSMQFrankXuLei.rar
參考文章:
1.programming WCF services
 本文轉自 frankxulei 51CTO部落格,原文連結:http://blog.51cto.com/frankxulei/320421,如需轉載請自行聯絡原作者


相關文章