WCF MSMQ队列基本概念简述

开发 开发工具
WCF MSMQ队列的类型可以被分为两种,一种为事务性队列,而另外一种则为非事务性队列。接下来我们将会针对这方面知识做一个详细介绍。

今天,我们将会在这篇文章中为大家详细介绍一下关于WCF MSMQ队列的一些基本特性。希望对于初学者来说,可以从这里介绍的内容中获得一些帮助,并能够充分掌握这些基本技巧,以方便我们的实际应用。

WCF MSMQ队列中共有两种类型,事务性队列(transactional queue)会将消息持久(persiste)存储到磁盘中,即便服务器当机(shutdown)、重启(reboot)或崩溃(crash),消息依然可以在系统恢复后被读取。同时,消息发布、获取和删除都在环境事务范围内,从而确保消息的可靠性。我们还可以使用 TransactionScope 将环境事务传递给队列,否则队列会自动创建一个内部事务。非事务性队列(nontransactional volatile queues)只是将消息存在内存,不会使用磁盘进行持久存储,且不会使用事务来保护对消息的操作。一但服务器发生问题,或者调用方出现异常,消息都会丢失。

  1. // 创建事务性队列  
  2. MessageQueue.Create(@".\private$\myqueue", true);  
  3. // 创建非事务性队列  
  4. MessageQueue.Create(@".\private$\myqueue"); 

通过下面的例子我们会看到事务失败时,没有任何消息被写入队列。

  1. [ServiceContract]  
  2. public interface IService  
  3. {  
  4. [OperationContract(IsOneWay = true)]  
  5. void Test(int i);  
  6. }  
  7. [ServiceBehavior]  
  8. public class MyService : IService  
  9. {  
  10. [OperationBehavior]  
  11. public void Test(int i)  
  12. {  
  13. Console.WriteLine(i);  
  14. }  
  15. }  
  16. public class WcfTest  
  17. {  
  18. public static void Test()  
  19. {  
  20. if (!MessageQueue.Exists(@".\private$\myqueue"))  
  21. {  
  22. MessageQueue.Create(@".\private$\myqueue", true);  
  23. }  
  24. IService client = ChannelFactory<IService>.CreateChannel(  
  25. new NetMsmqBinding(NetMsmqSecurityMode.None),  
  26. new EndpointAddress("net.msmq://localhost/private/myqueue"));  
  27. try  
  28. {  
  29. using (TransactionScope scope = new TransactionScope())  
  30. {  
  31. using (client as IDisposable)  
  32. {  
  33. for (int i = 0; i < 10; i++)  
  34. {  
  35. client.Test(i);  
  36. if (i > 5) throw new Exception();  
  37. }  
  38. }  
  39. scope.Complete();  
  40. }  
  41. }  
  42. catch  
  43. {   
  44. }  
  45. AppDomain.CreateDomain("Server").DoCallBack(delegate  
  46. {  
  47. ServiceHost host = new ServiceHost(typeof(MyService),
    new Uri("net.msmq://localhost/private/myqueue"));  
  48. host.AddServiceEndpoint(typeof(IService), 
    new NetMsmqBinding(NetMsmqSecurityMode.None), "");  
  49. host.Open();  
  50. });  
  51. }  

这里需要对 "消息" 做一个澄清,当客户端发出调用(call)时,调用会被转换成 WCF Message,然后被包装到 MSMQ Message 中。如果客户端事务完成提交,那么 MSMQ Message 会被传递到队列并存储起来。相反,如果事务失败,消息会被丢弃。上面的例子中,我们将多个调用放到一个环境事务中,也可以将多个服务调用放到一个事务当中。如果队列服务不在当前机器上,也就是说使用 Public Queue 时,客户端的消息队列组件将承担 "代理(proxy)" 的角色。客户端的调用会首先存储到本地队列,然后再由本地队列转发给目标队列。这个转发过程同样受到事务保护。

要是开发非事务性消息队列服务,需要用到 NetMsmqBinding 的两个属性。将 Durable 设为 false,表示不使用事务方式访问消息队列。另外还得将 ExactlyOnce 设为 false,否则会抛出 InvalidOperationException 异常。

下面例子中,重启消息队列服务(Message Queuing)后,你会发现消息丢失。

  1. [ServiceContract]  
  2. public interface IService  
  3. {  
  4. [OperationContract(IsOneWay = true)]  
  5. void Test(int i);  
  6. }  
  7. [ServiceBehavior]  
  8. public class MyService : IService  
  9. {  
  10. public MyService()  
  11. {  
  12. Console.WriteLine("Constructor...");  
  13. }  
  14. [OperationBehavior(TransactionScopeRequired=true)]  
  15. public void Test(int i)  
  16. {  
  17. Console.WriteLine(i);  
  18. }  
  19. }  
  20. public class WcfTest  
  21. {  
  22. public static void Test()  
  23. {  
  24. MessageQueue.Delete(@".\private$\myqueue");  
  25. MessageQueue.Create(@".\private$\myqueue");  
  26. NetMsmqBinding binding1 = new NetMsmqBinding
    (NetMsmqSecurityMode.None);  
  27. binding1.Durable = false;  
  28. binding1.ExactlyOnce = false;  
  29. IService client = ChannelFactory<IService>
    .CreateChannel(binding1,  
  30. new EndpointAddress("net.msmq://localhost/private/myqueue"));  
  31. using (client as IDisposable)  
  32. {  
  33. for (int i = 0; i < 10; i++)  
  34. {  
  35. client.Test(i);  
  36. }  
  37. }  
  38. Console.WriteLine("重启MSMQ服务,然后按任意键继续...");  
  39. Console.ReadKey(true);  
  40. AppDomain.CreateDomain("Server").DoCallBack(delegate  
  41. {  
  42. NetMsmqBinding binding2 = new NetMsmqBinding
    (NetMsmqSecurityMode.None);  
  43. binding2.Durable = false;  
  44. binding2.ExactlyOnce = false;  
  45. ServiceHost host = new ServiceHost(typeof(MyService),
    new Uri("net.msmq://localhost/private/myqueue"));  
  46. host.AddServiceEndpoint(typeof(IService), binding2, "");  
  47. host.Open();  
  48. });  
  49. }  

【编辑推荐】

  1. PDA访问WCF实现重点在过程
  2. WCF标准终结点基本概念剖析
  3. WCF回调操作是鸡应用技巧讲解
  4. WCF元数据交换应用技巧分享
  5. IIS托管WCF服务实际操作中常见错误分析
责任编辑:曹凯 来源: 豆豆网
相关推荐

2010-03-01 14:50:30

WCF行为类型

2010-02-23 16:32:29

WCF服务

2009-12-21 10:27:52

WCF基本概念

2010-03-01 18:04:35

WCF配置绑定

2009-12-21 15:33:07

WCF集合元素

2010-02-24 17:17:04

WCF宿主环境

2010-03-01 16:25:07

WCF体系架构

2010-03-02 16:22:31

WCF状态应用

2009-12-21 16:52:02

WCF序列化

2010-03-01 16:41:04

WCF数据表

2009-12-21 14:37:14

2009-12-22 10:16:54

WCF服务状态

2010-03-02 11:10:43

WCF标准终结点

2010-02-25 14:46:31

2010-03-01 17:57:11

WCF缓存机制

2010-03-03 15:10:49

第三方Python库

2011-03-28 11:05:17

ODBC

2014-04-16 15:11:19

Spark

2012-09-11 14:39:03

Moosefs

2009-03-20 11:46:10

MGCP协议网关
点赞
收藏

51CTO技术栈公众号