[WCF MSMQ] 2. 队列与事务
来源:互联网 发布:中国联通wap网络 编辑:程序博客网 时间:2024/05/20 16:43
MSMQ 支持两种类型的队列,事务性队列(transactionalqueue)会将消息持久(persiste)存储到磁盘中,即便服务器当机(shutdown)、重启(reboot)或崩溃(crash),消息依然可以在系统恢复后被读取。同时,消息发布、获取和删除都在环境事务范围内,从而确保消息的可靠性。我们还可以使用 TransactionScope将环境事务传递给队列,否则队列会自动创建一个内部事务。非事务性队列(nontransactional volatilequeues)只是将消息存在内存,不会使用磁盘进行持久存储,且不会使用事务来保护对消息的操作。一但服务器发生问题,或者调用方出现异常,消息都会丢失。
MessageQueue.Create(@"./private$/myqueue", true);
// 创建非事务性队列
MessageQueue.Create(@"./private$/myqueue");
通过下面的例子我们会看到事务失败时,没有任何消息被写入队列。
public interface IService
{
[OperationContract(IsOneWay = true)]
void Test(int i);
}
[ServiceBehavior]
public class MyService : IService
{
[OperationBehavior]
public void Test(int i)
{
Console.WriteLine(i);
}
}
public class WcfTest
{
public static void Test()
{
if (!MessageQueue.Exists(@"./private$/myqueue"))
{
MessageQueue.Create(@"./private$/myqueue", true);
}
IService client = ChannelFactory<IService>.CreateChannel(
new NetMsmqBinding(NetMsmqSecurityMode.None),
new EndpointAddress("net.msmq://localhost/private/myqueue"));
try
{
using (TransactionScope scope = new TransactionScope())
{
using (client as IDisposable)
{
for (int i = 0; i < 10; i++)
{
client.Test(i);
if (i > 5) throw new Exception();
}
}
scope.Complete();
}
}
catch
{
}
AppDomain.CreateDomain("Server").DoCallBack(delegate
{
ServiceHost host = new ServiceHost(typeof(MyService),
new Uri("net.msmq://localhost/private/myqueue"));
host.AddServiceEndpoint(typeof(IService), new NetMsmqBinding(NetMsmqSecurityMode.None), "");
host.Open();
});
}
}
这里需要对 "消息" 做一个澄清,当客户端发出调用(call)时,调用会被转换成 WCF Message,然后被包装到 MSMQ Message中。如果客户端事务完成提交,那么 MSMQ Message会被传递到队列并存储起来。相反,如果事务失败,消息会被丢弃。上面的例子中,我们将多个调用放到一个环境事务中,也可以将多个服务调用放到一个事务当中。如果队列服务不在当前机器上,也就是说使用 Public Queue 时,客户端的消息队列组件将承担 "代理(proxy)"的角色。客户端的调用会首先存储到本地队列,然后再由本地队列转发给目标队列。这个转发过程同样受到事务保护。下图很好地对事务性队列操作做了个说明。
要是开发非事务性消息队列服务,需要用到 NetMsmqBinding 的两个属性。将 Durable 设为false,表示不使用事务方式访问消息队列。另外还得将 ExactlyOnce 设为 false,否则会抛出InvalidOperationException 异常。
下面例子中,重启消息队列服务(Message Queuing)后,你会发现消息丢失。
public interface IService
{
[OperationContract(IsOneWay = true)]
void Test(int i);
}
[ServiceBehavior]
public class MyService : IService
{
public MyService()
{
Console.WriteLine("Constructor...");
}
[OperationBehavior(TransactionScopeRequired=true)]
public void Test(int i)
{
Console.WriteLine(i);
}
}
public class WcfTest
{
public static void Test()
{
MessageQueue.Delete(@"./private$/myqueue");
MessageQueue.Create(@"./private$/myqueue");
NetMsmqBinding binding1 = new NetMsmqBinding(NetMsmqSecurityMode.None);
binding1.Durable = false;
binding1.ExactlyOnce = false;
IService client = ChannelFactory<IService>.CreateChannel(binding1,
new EndpointAddress("net.msmq://localhost/private/myqueue"));
using (client as IDisposable)
{
for (int i = 0; i < 10; i++)
{
client.Test(i);
}
}
Console.WriteLine("重启MSMQ服务,然后按任意键继续...");
Console.ReadKey(true);
AppDomain.CreateDomain("Server").DoCallBack(delegate
{
NetMsmqBinding binding2 = new NetMsmqBinding(NetMsmqSecurityMode.None);
binding2.Durable = false;
binding2.ExactlyOnce = false;
ServiceHost host = new ServiceHost(typeof(MyService),
new Uri("net.msmq://localhost/private/myqueue"));
host.AddServiceEndpoint(typeof(IService), binding2, "");
host.Open();
});
}
}
- [WCF MSMQ] 2. 队列与事务
- MSMQ消息队列与WCF MSMQ的认识与使用
- WCF服务离线操作与消息队列MSMQ
- (6)WCF服务离线操作与消息队列MSMQ
- WCF分布式开发步步为赢(13):WCF服务离线操作与消息队列MSMQ
- MSMQ与redis队列
- WCF--MSMQ
- WCF分布式开发必备知识(1):MSMQ消息队列
- 化零为整WCF(16) - 消息队列(MSMQ - MicroSoft Message Queue)
- WCF分布式开发必备知识(1):MSMQ消息队列
- 化零为整WCF(16) - 消息队列(MSMQ - MicroSoft Message Queue)
- [Forward]WCF分布式开发必备知识(1):MSMQ消息队列
- 化零为整WCF(16) - 消息队列(MSMQ - MicroSoft Message Queue)
- 使用MSMQ消息队列的WCF的效率的问题。
- wcf的 msmq
- 基于MSMQ使用WCF
- 基于MSMQ使用WCF
- MSMQ In WCF
- [WCF Transaction] 3. 事务投票
- 基于消息驱动的面向对象通用C/S应用框架(一)
- 基于消息驱动的面向对象通用C/S应用框架(二)
- [WCF Transaction] 4. 事务与会话
- [WCF MSMQ] 1. 基本应用
- [WCF MSMQ] 2. 队列与事务
- 基于消息驱动的面向对象通用C/S应用框架(三)
- WCF - 只读属性
- 基于消息驱动的面向对象通用C/S应用框架(四)
- WCF - MessageLogging
- WCF Essentials (1)
- 基于消息驱动的面向对象通用C/S应用框架(五)
- 实现下载的代码?请指教
- WCF Essentials (2)