• 1. 企业级应用—消息队列
  • 2. 回顾什么是缓存依赖? 缓存依赖有几种形式? 2000操作系统如何配置缓存依赖?
  • 3. 本章目标了解消息队列 掌握私有队列的创建 掌握如何发送简单消息 掌握如何发送复杂消息 掌握如何发送图片类消息 掌握如何接受消息 掌握如何发送事务消息
  • 4. 消息队列简介我们都用过手机发短信,发送方发端信的时候并不知道接受方是否开机,接受方在开机的时候收到的短信并不知道发送方什么时候发送的。消息队列的工作原理也类似于手机发短信的模式—异步通信。 问题思考: 在电子商务网站中需要对订单做处理,处理订单一般会分发到不同的业务员手中,业务员只有在营业结束才能知道手中订单是否处理完毕,所以在客户订购商品的时候,无法知道此订单指派给那个业务员。该如何解决这个问题?
  • 5. 续上微软操作系统的消息队列技术很好的解决了这个问题。 发送者订单订单订单订单订单订单订单接收者订单订单队列即使关机, 订单还可以恢复
  • 6. 运行环境Message Queuing是操作系统的一部分,现在版本是3.0所以不能运行在windows 2000操作系统上,只能运行在Windows 2003和Windows XP上面
  • 7. 如何安装Message Queuing
  • 8. 队列的形式消息对列是一个消息库,存储在磁盘上的消息位于\system32\msmq\storage目录中 公共队列(传出队列):在Active Directory(活动目录)中发布,这时候要求计算机工作在域模式下,不能在workgroup模式下重建公共队列,这一部分内容涉及到更多操作系统方面知识,以及消息的不安全考虑,这方面知识以自学为主。
  • 9. 续上私有队列:只有知道该队列的完整路径名称才可以访问,在工作组模式中可以创建队列。这是本章掌握的重点,也是入门的起点。 日志队列: 死信队列: 管理队列:
  • 10. 如何创建队列两种方式: Computer Management MMC插件创建(操作系统管理工具) 编程方式创建(这是重点)
  • 11. C#中如何操作消息队列命名空间:System.Messaging 涉及到的类: MessageQueue:负责队列的创建 Message:负责消息的创建
  • 12. 发送简单消息通过案例的形式学习队列的创建以及消息的发送接收。 案例1:发送简单消息.aspx实现的功能有 创建队列 发送消息 接受消息
  • 13. 效果图操作流程 1:先创建队列,如果队列已经存在将提示错误 2:发送消息,缺省的消息队列最大容量将是无限制的 3:接收消息,可以接收文字、图片、视频、声音,目前只能接受文字
  • 14. 代码实现/// /// 创建私有队列 /// /// /// protected void Button3_Click(object sender, EventArgs e) { if (MessageQueue.Exists(@".\Private$\" + this.txtPri.Text.Trim())) { Response.Write("队列已经创建请更换名称"); } else { msg = MessageQueue.Create(@".\Private$\" + this.txtPri.Text.Trim()); } }/// /// 发送私有消息 /// /// /// protected void Button1_Click(object sender, EventArgs e) { try { if (!MessageQueue.Exists(@".\Private$\" + this.txtPri.Text.Trim())) { Response.Write("队列不存在请创建队列"); } else { msg = new MessageQueue(@".\Private$\" + this.txtPri.Text.Trim()); msg.Send(DateTime.Now.ToString() + ":" + this.txtSendMsg.Text, "标签1"); } } catch (Exception ee) { Response.Write(ee.Message); } } /// /// 接收消息 /// /// /// protected void Button2_Click(object sender, EventArgs e) { msg = new MessageQueue(@".\Private$\" + this.txtPri.Text.Trim()); msg.Formatter = new XmlMessageFormatter(new string[] { "System.String" }); Message msgs= msg.Receive(TimeSpan.FromSeconds(3));//等待3秒 this.txtAcceMsg.Text = msgs.Body.ToString(); }
  • 15. 如何发送复杂消息不仅能发送文字之类的简单消息,还可以发送自定义的对象,比如某个学生对象。 案例:发送复杂消息.aspx实现的功能有 创建队列 发送对象 接收对象
  • 16. 效果图用户输入姓名、年龄后点击发送消息,把学生对象发送到队列中。 接收消息可以还原队列中的学生对象
  • 17. 代码实现/// /// 学生类 /// [Serializable] public class Student { private string sname; public string Sname { get { return sname; } set { sname = value; } } private int age; public int Age { get { return age; } set { age = value; } } public Student() { }/// /// 发送消息 /// /// /// protected void Button2_Click(object sender, EventArgs e) {//检查队列是否存在 if (!isQueneExists(qn)) Response.Write("请添加队列"); else { Student s1 = new Student(); s1.Sname = this.txtSN.Text.Trim(); s1.Age = Convert.ToInt32(this.txtAge.Text); msq = new MessageQueue(qn); msq.Send(s1, "第二个学生"); } }/// /// 接收消息 /// /// /// protected void Button3_Click(object sender, EventArgs e) { if (!isQueneExists(qn)) Response.Write("请添加队列"); else { msq = new MessageQueue(qn); Message msg = msq.Receive(TimeSpan.FromSeconds(3)); msg.Formatter = new XmlMessageFormatter(new Type[] { typeof(Student)}); Student s1 = (Student)msg.Body; this.lblName.Text = s1.Sname; this.lblAge.Text = s1.Age.ToString(); } }
  • 18. 如何发送图片类消息当我们需要发送图片等二进制类的消息时候,那么该怎么发送呢? 案例:发送图片.aspx实现的功能有 为了演示发送图片消息的功能,取消了创建队列的功能,那么图片发送到photo队列中. 接收图片功能直接在页面中显示出来
  • 19. 效果图点击发送图片功能,直接把页面图片发送到对列中 点击读取图片按钮,页面会显示读取到的图片
  • 20. 代码实现/// /// 发送图片 /// /// /// protected void btnSend_Click(object sender, EventArgs e) { MessageQueue msq = new MessageQueue(@".\Private$\photo"); FileStream fs = new FileStream(Server.MapPath("~/images/IMAGE_00028.jpg"), FileMode.Open); byte[] imgs = new byte[(int)fs.Length]; fs.Read(imgs, 0, (int)fs.Length); msq.Send(imgs, "发送一张图片"); }/// /// 接收图片 /// /// /// protected void btnReadImg_Click(object sender, EventArgs e) { try { MessageQueue msq = new MessageQueue(@".\Private$\photo"); //新消息到来之前等待3秒 Message msg = msq.Receive(TimeSpan.FromSeconds(3)); msg.Formatter = new XmlMessageFormatter(new Type[] { typeof(System.Byte[]) });//消息格式化 byte[] bits = (byte[])msg.Body; //MemoryStream ms = new MemoryStream(bits); //Response.BinaryWrite(ms.ToArray()); Response.BinaryWrite(bits);//输出图片 } catch (Exception ee) { Response.Write("没有消息了"); } }
  • 21. 可恢复消息什么是可恢复消息 在计算机出现异常的情况下,如(断电、异常关机、网络断开)消息不被丢失,这类消息就是可恢复消息,否则的话消息很容易丢失。 案例:可恢复消息.aspx实现的功能就是 点击发送消息按钮可以把文本框中的消息发送到可恢复消息队列中 点击恢复消息可以读取队列中的消息 为了测试效果,消息发送完毕请重新启动机器
  • 22. 效果图只能发送普通消息。 在断电的情况下同样可以恢复消息 同样的测试环境看能不能恢复上面案例中的图片
  • 23. 代码实现/// /// 发送可恢复消息 /// /// /// protected void Button1_Click(object sender, EventArgs e) { MessageQueue msq = new MessageQueue(@".\Private$\可恢复消息"); Message msg = new Message(this.TextBox1.Text.Trim()); msg.Priority = MessagePriority.High;//设置消息优先级 msg.Recoverable = true;//设置消息可恢复 msq.Send(msg, "消息备份"); } /// /// 接收可恢复消息 /// /// /// protected void Button2_Click(object sender, EventArgs e) { MessageQueue msq = new MessageQueue(@".\Private$\可恢复消息"); Message msg = msq.Receive(TimeSpan.FromSeconds(3)); msg.Formatter = new XmlMessageFormatter(new Type[] { typeof(string) }); this.Label1.Text = msg.Body.ToString(); }
  • 24. 事务消息问题思考: 虽然可恢复消息能够保证消息不被丢失,但是不能保证消息的顺序读取,也不能保证消息的只读一次。这个问题该怎么解决呢? 事务消息:是可恢复消息的特殊版本,不但能够实现消息的可恢复功能,还可以保证消息的按顺序读取。
  • 25. 效果图创建事务消息队列(注该队列具备事务性) 依次发送4个文字消息,然后关机重新启动机器 点击接收事务消息按钮,依次显示事务消息
  • 26. 代码实现MessageQueue msq = new MessageQueue(@".\Private$\事务消息"); MessageQueueTransaction tran = new MessageQueueTransaction();/// /// 发送事务消息 /// /// /// protected void Button1_Click(object sender, EventArgs e) { try { tran.Begin();//事务开始 msq.Send(this.txtTMsg1.Text, tran); msq.Send(this.txtTMsg2.Text, tran); msq.Send(this.txtTMsg3.Text, tran); msq.Send(this.txtTMsg4.Text, tran); tran.Commit();//事务提交 } catch(Exception ee) { tran.Abort(); } }/// /// 接收事务消息 /// /// /// protected void btnReceive_Click(object sender, EventArgs e) { string str = string.Empty; //第一个消息 Message msg = msq.Receive(TimeSpan.FromSeconds(3)); msg.Formatter = new XmlMessageFormatter(new Type[] { typeof(string) }); str = (string)msg.Body; this.labMsg1.Text = str; //第二个消息 msg = msq.Receive(TimeSpan.FromSeconds(3)); msg.Formatter = new XmlMessageFormatter(new Type[] { typeof(string) }); str = (string)msg.Body; this.labMsg2.Text = str; //第三个消息 msg = msq.Receive(TimeSpan.FromSeconds(3)); msg.Formatter = new XmlMessageFormatter(new Type[] { typeof(string) }); str = (string)msg.Body; this.labMsg3.Text = str; //第四个消息 msg = msq.Receive(TimeSpan.FromSeconds(3)); msg.Formatter = new XmlMessageFormatter(new Type[] { typeof(string) }); str = (string)msg.Body; this.labMsg4.Text = str; }
  • 27. 总结消息队列有几种形式 如何才能实现消息不被丢失 如何实现事务消息 如何发送复杂消息
  • 28. 消息队列是做异步处理用的,简单说就是两个程序,一个把任务发到队列中,另一个从消息队列中把任务读出来,完成两个程序的异步处理。