用MsmqBinding投送message出现的一个灵异事件 【第二篇】

简介:

  一直都在用Msmqbinding,也一直忽视了message里面的内容格式是什么样的,这也是微软给我们高层封装带给我们的开发效率,但同时一旦中间出了什么问题,

就不知道从何查起了。有个需求是这样的,服务端和客户端采用离线连接,也就是消息队列模式,server接收端在处理消息的时候,要根据一定的逻辑,如果该消息不

满足规则,就把消息原样的丢回消息队列中,问题就出现在这里。。。消息丢进去了,然后,然后就tmd的飞走了!!!先快速的看下代码。

一:示例代码

1.server端

public void Run(Test test)
 {
 if (test.str.Length % 10 == 0)
 {
 //重新丢回消息队列
 MessageQueue mq = new MessageQueue(@".\private$\myqueue");
 Message msg = new Message();
 msg.Body = test;
 msg.Formatter = new XmlMessageFormatter(new Type[] { test.GetType() });

 mq.Send(msg);
 //Environment.Exit(0);

 System.Console.WriteLine("已经成功丢回! ,当前线程:" + Thread.CurrentThread.ManagedThreadId);
 }
 else
 {
 System.Console.WriteLine("已经消费客户端消息!");
 }
 }

2.服务代码
public void Run(Test test)
 {
 if (test.str.Length % 10 == 0)
 {
 //重新丢回消息队列
 MessageQueue mq = new MessageQueue(@".\private$\myqueue");
 Message msg = new Message();
 msg.Body = test;
 msg.Formatter = new XmlMessageFormatter(new Type[] { test.GetType() });

 mq.Send(msg);
 //Environment.Exit(0);

 System.Console.WriteLine("已经成功丢回! ,当前线程:" + Thread.CurrentThread.ManagedThreadId);
 }
 else
 {
 System.Console.WriteLine("已经消费客户端消息!");
 }
 }

3.client端
static void Main(string[] args)
 {
 var msmq = new NetMsmqBinding(NetMsmqSecurityMode.None);

 msmq.ExactlyOnce = false;

 ChannelFactory<IHomeService> factory = new ChannelFactory<IHomeService>(msmq,
 "net.msmq://localhost/private/myqueue");

 var client = factory.CreateChannel();

 for (int i = 0; i < int.MaxValue; i++)
 {
 var t = new Test() { str = "1111111111" };

 client.Run(t);
 Console.WriteLine("调用第 " + i + " 次");
 }

 var s = 10;
 }

当时写的急,也没关注能不能用MessageQueue将消息丢回消息队列中,然后让WCF的MsmqBinding去读取,结果上面的奇葩问题就来了,反正队列中的数据

一直在减少,但是server端就是没进来,tmd的wcf却一个错误都不抛出来,麻蛋。。。为了展示出效果,我特意做成了flash。

从上面的flash中,你可以看到console控制台已经不在接受消息了,但是奇怪的是消息队列中的数据还是一直在减少。。。。

二:怀疑

  从开始在server端将message丢回消息队列的时候,我就有一点怀疑,或许这两种message的内容格式不一样,wcf在接受的时候应该会报错,但是tmd的

就是没有给小爷报错,现在既然问题来了,我就去比较一下,到底两种message的格式是什么样的,然后我就写了两份丢消息队列的方法。

static void Main(string[] args)
 {
 //第一种方式:
 var msmq = new NetMsmqBinding(NetMsmqSecurityMode.None);
 msmq.ExactlyOnce = false;

 ChannelFactory<IHomeService> factory = new ChannelFactory<IHomeService>(msmq,
 "net.msmq://localhost/private/myqueue");
 var client = factory.CreateChannel();

 var t = new Test() { str = "1111111111" };

 client.Run(t);


 //第二种方式:
 MessageQueue mq = new MessageQueue(@".\private$\myqueue");
 Message msg = new Message();
 msg.Body = t;
 msg.Formatter = new XmlMessageFormatter(new Type[] { t.GetType() });

 mq.Send(msg);
 }

然后我跑去MMC控制台看一下,果然消息的大小都不一样,内容也不一样。。。真相大白,左边也不知道是什么格式,右边很清楚的看到是xml格式。

如果文章到这里的话,说明我也就只能看表面现象,因为刚才我已经提出了一个问题,左边到底是什么格式???

三:进一步探索

  现在我们知道Msmqbinding使用的是自己独有格式的消息body,现在是不是有耐心看看wcf这个底层怎么写的呢???我通过一系列的调试跟踪,

发现MsmqBinding是先创建一个Msmq的信道栈,可以看到这个channel要传递的消息是soap12协议的,不管是什么样的,可以确认的是,消息传递

采用的soap消息的模式。对吧,如下图:

接下来,这个channel会调用wcf自己封装的消息队列MsmqQueue,并且会调用其中的send方法,将消息推送到消息队列中,不过要记住,wcf中那

些高层的msmq操作,在底层都是这个类来达到效果的。

好了,探索就到这里为止了,到现在我们起码知道以下二点消息了。


相关文章
|
2月前
|
人工智能 大数据
碰撞事件探究
【10月更文挑战第21天】碰撞事件是一个充满奥秘和挑战的研究领域。深入理解碰撞的原理和规律,不仅有助于我们解决实际问题,也能让我们更好地认识自然界的运行机制。随着科学技术的不断进步,我们对碰撞事件的研究将不断深入,为人类的发展和进步提供更多的知识和启示。还可以结合具体的实验案例、实际应用和科学发现,进一步拓展和丰富对碰撞事件的探讨,使其更加全面和深入。
34 0
|
4月前
|
C#
由浅入深理解C#中的事件
由浅入深理解C#中的事件
112 19
|
前端开发
前端学习笔记202305学习笔记第二十五天-事件注册和调用
前端学习笔记202305学习笔记第二十五天-事件注册和调用
38 0
|
JavaScript API
StencilJs 学习之事件
其实并没有所谓的 stencil Event,相反 stencil 鼓励使用 DOM event。然而,Stencil 提供了一个 API 来指定组件可以触发的事件,以及组件监听的事件。 这是通过 Event()和 Listen()装饰器实现的。
81 0
|
JavaScript
WebApi入门第三章(事件介绍及注册事件 )
WebApi入门第三章(事件介绍及注册事件 )
130 0
WebApi入门第三章(事件介绍及注册事件 )
|
测试技术
软件测试面试题:如何处理一个alert弹窗?
软件测试面试题:如何处理一个alert弹窗?
215 0
|
JavaScript 前端开发
【重温基础】20.事件
【重温基础】20.事件
127 0
|
资源调度 程序员 C#