在WCF中使用消息隊列
在一些大型的解決方案中,假設我們的服務沒有辦法一直在線,或者因為這樣那樣的原因宕機了,有沒有什么辦法讓客戶端的影響最小化呢?答案是可以通過消息隊列的方式,哪怕服務是沒有在線的,客戶端依然可以繼續操作。
1. 首先來學習一些消息隊列的基礎知識
消息隊列默認是沒有安裝的,可以通過下面的方式進行安裝
2. 通過一個小程序來演示一下如何發送和接受消息
static void SendMessage() {
Message msg = new Message("這是我的一個消息");
string queueName = @".\Private$\SampleQueue";
MessageQueue mq = null;
if (!MessageQueue.Exists(queueName))
mq = MessageQueue.Create(queueName);
else
mq = new MessageQueue(queueName);
mq.Formatter = new XmlMessageFormatter(new[] { "System.String" });
mq.Send(msg, "測試消息");
Console.WriteLine("消息發送成功");
}
然后,我們就可以看到這個消息了(通過mmc控制臺)
[注意]xp和vista或者win 7都屬于桌面操作系統,它們只支持私有隊列。如果是服務器操作系統的話,則還支持公共隊列。
下面看看如何讀取隊列中的消息
static void ReadMessage() {
string queueName = @".\Private$\SampleQueue";
MessageQueue mq = new MessageQueue(queueName);
mq.Formatter = new XmlMessageFormatter(new[] { "System.String" });
Message msg = mq.Receive();
Console.WriteLine(msg.Label);
Console.WriteLine(msg.Body.ToString());
}
上面是一個很簡單的例子,演示了如何發送和接收消息。
下面用一個例子來講解WCF中如何利用消息隊列來實現異步的服務。
1. 創建契約
using System;
using System.ServiceModel;
using System.Runtime.Serialization;
namespace Contracts
{
[ServiceContract]
public interface IMSMQService
{
[OperationContract(IsOneWay = true)]
void PlaceOrder(OrderEntry entry);
}
[DataContract]
public class OrderEntry {
[DataMember]
public int OrderID { get; set; }
[DataMember]
public DateTime OrderDate { get; set; }
[DataMember]
public int Quantity { get; set; }
[DataMember]
public int UnitPrice { get; set; }
public override string ToString()
{
return string.Format(
"ID:{0}\tDate:{1}\tQuantity:{2}\tUnitPrice:{3}\t",
OrderID,
OrderDate,
Quantity,
UnitPrice);
}
}
}
2. 實現服務
using System;
namespace Services
{
public class MSMQOrderService:Contracts.IMSMQService
{
#region IMSMQService 成員
public void PlaceOrder(Contracts.OrderEntry entry)
{
Console.WriteLine("收到訂單:{0}", entry);
}
#endregion
}
}
3. 創建宿主
using System;
using System.ServiceModel;
namespace Host
{
class Program
{
static void Main(string[] args)
{
using (ServiceHost host =
new ServiceHost(
typeof(Services.MSMQOrderService),
new Uri("net.msmq://localhost/Private/SampleQueue")
))
{
NetMsmqBinding binding = new NetMsmqBinding(NetMsmqSecurityMode.None);
binding.ExactlyOnce = false;
binding.Durable = true;
host.AddServiceEndpoint(
typeof(Contracts.IMSMQService).FullName,
binding,
"");
host.Open();
Console.WriteLine("服務器已經準備好");
Console.Read();
}
}
}
}
4. 創建客戶端
using System;
using System.ServiceModel;
namespace Client
{
class Program
{
static void Main(string[] args)
{
NetMsmqBinding binding = new NetMsmqBinding(NetMsmqSecurityMode.None);
binding.ExactlyOnce = false;
binding.Durable = true;
ChannelFactory<Contracts.IMSMQService> channel =
new ChannelFactory<Contracts.IMSMQService>(
binding, new EndpointAddress("net.msmq://localhost/Private/SampleQueue"));
Contracts.IMSMQService client =
channel.CreateChannel();
client.PlaceOrder(
new Contracts.OrderEntry()
{
OrderID = 1,
OrderDate = DateTime.Now,
UnitPrice = 10,
Quantity = 10
});
Console.WriteLine("發送了一個訂單");
Console.Read();
}
}
}
5. 測試
很好,我們看到消息發送到了服務器端。但,如果僅僅是這樣,那么使用消息隊列有什么優勢呢?
我們現在不啟動服務端,而僅僅啟動客戶端。看看是否可以發出訂單
我們發現,雖然服務沒有開啟來,但是卻依然可以發出訂單。那么這個訂單到哪里去了呢。原來是被存放到了隊列中。如下圖所示
然后,我們再去開服務宿主程序。
宿主程序會自動讀取消息隊列中的消息,并自動進行處理。此時再次去查看隊列的話,就會發現已經沒有消息了

浙公網安備 33010602011771號