最近研究了一下基於MSMQ的WCF應用,從書上、網上查了很多資料,但始終沒能徹底理解WCF-MSMQ的工作原理,也沒能得到一個合理的應用解決方案。索性還是自己做個實驗,探索一下吧。經過反復試驗,頗有收獲,現跟大家分享一下。
首先我的解釋一下為什么查了那么多資料卻未能理解WCF-MSMQ的工作原理,不是各位大牛沒有把原理講清楚,而是大多數給出的例子都是在單機上運行的,這就很難說明白離線工作的原理。
為了說明問題,我用了四台虛機來部署我的實驗程序,首先我給大家看一下我的程序部署結構:
4台虛機(紅線表示消息流向),它們的操作系統都是Windows2008 R2,並且都需要安裝MSMQ服務,否則無法工作。也就是說,如果應用程序客戶端發布出去以后,要想實現離線提交,在客戶端機器上也必須安裝MSMQ服務。
- WCF Host (10.222.114.76):這台機器用來運行Service程序,它的主要任務是監聽MSMQ Host這台機器上的隊列。
- MSMQ Host (10.222.114.78):這台機器用來提供消息服務;當然完全可以由這4台機器的任何一台作為MSMQ的消息服務器,我MSMQ Host這台機器是為了說明一個問題,稍后會提到。
- WCF Client 1 (10.222.114.77),WCF Client 2 (10.222.114.79):用來運行客戶端程序,當然我們可以有無數個客戶端。
接下來看一下WCF程序的配置:
服務端
<system.serviceModel> <bindings> <netMsmqBinding> <binding name="msmqBinding" queueTransferProtocol="Srmp"> <security mode="None" /> </binding> </netMsmqBinding> </bindings> <services> <service name="WCF.Msmq.MsmqService"> <endpoint address="net.msmq://10.222.114.78/private/myqueue" binding="netMsmqBinding" bindingConfiguration="msmqBinding" contract="WCF.Msmq.IMsmqService" /> </service> </services> </system.serviceModel>
客戶端
<system.serviceModel> <bindings> <netMsmqBinding> <binding name="netMsmqBinding" queueTransferProtocol="Srmp"> <security mode="None" /> </binding> </netMsmqBinding> </bindings> <client> <endpoint address="net.msmq://10.222.114.78/private/myqueue" binding="netMsmqBinding" bindingConfiguration="netMsmqBinding" contract="WCF.Msmq.IMsmqService" name="msmqserivce" /> </client> </system.serviceModel>
有一點需要指出,那就是Address。和其它綁定方式不同,使用MSMQ的WCF的地址並不是本機IP(大家可以看到我的WCF Host這台機器的IP是10.222.114.76,像我們常用的basicHttpBingding,WSHttpBingDing等地址指向都是本機地址),而是MSMQ Host那台虛機的IP地址。這就是我為什么把專門用MSMS Host單獨拿出來作為消息服務器的原因。另外, queueTransferProtocol="Srmp"用的使用 SOAP 可靠消息傳送協議 (SRMP),需要安裝HTTP支持,可以直接把它刪掉使用默認的Native方式。
這里代碼我就不往上貼了,看一下執行過程吧,WCF Client 1,WCF Client 2往MSMQ Host這台機器上發送消息,WCF Host監控MSMQ Host這台機器上的private/myqueue對列,一旦有消息,則把消息提取出來進行處理。下面是我的程序運行結果,在運行程序之前,需要在MSMQ Host上創建一個私有隊列private/myqueue。
WCF Client 1執行結果 | WCF Client 2執行結果 | WCF Host 執行結果 |
![]() |
![]() |
![]() |
我們接下來看下離線工作。我們把WCF Client 1的網卡禁用,或者停掉MSMQ Host,會看到以下結果,在Outgonging隊列里堆積了很多發不出去的消息。這就是為什么在客戶端需要安裝MSMQ服務的原因。一旦WCF Client 1與MSMQ Host再次建立連接,在Outgoing隊列里的消息就會被發送到MSMQ Host上去。
關閉WCF Host中我們運行的Service程序,這時會看到,在MSMQ Host這台機器上private/myqueue對列中的消息越積越多。等到再次啟動Service后,它里面的消息就會被處理掉。
經過上面的實驗,可以得到一下結論:WCF Host,MSMQ Host,WCF Client這三台機器任何一台發生故障,應用都是可恢復的,而且數據不會丟失。
接下來我還做了另一個實驗,就是在另外一台機器上啟動新建的WCF服務程序,發現兩個Service都可以去處理同一隊列中的消息,從這種意義上來說,這不失是一個負載均衡的一個解決方案。
最后,附上我的實驗代碼,供大家參考:Msmq.7z