MSMQ消息通知系统之消息队列创建、发送、接收

--背景

1.消息通知系统。

2.在进行系统设计时,除了对安全、事务等问题给与足够的重视外,性能也是一个不可避免的问题所在,尤其是一个B/S结构的软件系统,必须充分地考虑访问量、数据流量、服务器负荷的问题。解决性能的瓶颈,除了对硬件系统进行升级外,软件设计的合理性尤为重要。对于一些实时性不是很高的模块我们可以使用了Microsoft Messaging Queue(MSMQ)技术来完成异步处理,利用消息队列临时存放要操作的数据,使得数据访问因为不需要访问数据库从而提高了访问性能,至于队列中的数据,则等待系统空闲的时候再进行处理。[部分语言来自张逸blog: http://www.cnblogs.com/wayfarer/]

3.消息通知系统就是利用MSMQ技术、window服务实现一系列的通知服务

 

 

--结构图

--消息队列的安装

关于消息队列的基本知识,我在这里就不多说了。大家可以看看下面的资料

http://www.cnblogs.com/rickie/archive/2004/11/16/64345.html

http://www.microsoft.com/china/msdn/events/webcasts/shared/webcast/consyscourse/ASPNETpractise.aspx

http://www.cnblogs.com/rickie/archive/2004/11/17/64712.html

http://www.cnblogs.com/wayfarer/archive/2007/03/15/496207.html

 

1:安装消息队列window组件,建立事务性专用队列[private$\] 

    a.通过控制面板,添加删除程序”->”添加/删除window组件”->安装MSMQ

    b.配置MSMQ:计算机管理-消息队列。在专有队列下创建指定的事务性队列.[ MsmsqQueue]

2: 可以使用installutil.exe安装编译后的exe windows服务

 

 

--消息体

消息是两台计算机间传送的数据单位,消息可以非常简单,例如只包含文本字符串;也可以很复杂,可能包含嵌入对象。

在进行消息操作前,我们先定义一个超类[SuperClass].以作为消息通知系统的消息体。

代码如下:

using System;

using System.Collections.Generic;

using System.Text;

 

namespace MsMqDemo

{

    [Serializable]

    public class MessageBase

    {

        /// <summary>

        /// 消息类型

        /// </summary>

        private string messagetype;

        public string MessageType

        {

            get { return messagetype; }

            set { messagetype = value; }

        }

        /// <summary>

        /// 消息内容

        /// </summary>

        private string messagebody;

        public string MessageBody

        {

            get { return messagebody; }

            set { messagebody = value; }

        }

    }

}

 

--消息的发送、接受

上面结构图的MsgRecorder就是消息的发送、接收器

在这个消息通知系统,我们可以借鉴Petshop4.0的消息处理的方式作为我们的MsgRecorder.

1>    消息接口IMessaging

using System;

using System.Collections.Generic;

using System.Text;

 

namespace MsMqDemo

{

    public interface IRecorder

    {

 

        /// <summary>

        /// Method to send an order to a message queue for later processing

        /// </summary>

        /// <param name="body">All information about an order</param>

        void Send(MessageBase msg);

        MessageBase Receive();

        MessageBase Receive(int timeout);

    }

}

2> PetShopQueue

using System;

using System.Messaging;

namespace MsmqDemo

{

    /// <summary>

    /// This could be a base class for all PetShop MSMQ messaging implementation as

    /// it provides a basic implementation for sending and receving messages to and from transactional queue

    /// </summary>

    public class PetShopQueue : IDisposable {

 

        protected MessageQueueTransactionType transactionType = MessageQueueTransactionType.Automatic;

        protected MessageQueue queue;

        protected TimeSpan timeout;

 

        public PetShopQueue(string queuePath, int timeoutSeconds) {

            queue = new MessageQueue(queuePath);

            timeout = TimeSpan.FromSeconds(Convert.ToDouble(timeoutSeconds));

 

            // Performance optimization since we don't need these features

            queue.DefaultPropertiesToSend.AttachSenderId = false;

            queue.DefaultPropertiesToSend.UseAuthentication = false;

            queue.DefaultPropertiesToSend.UseEncryption = false;

            queue.DefaultPropertiesToSend.AcknowledgeType = AcknowledgeTypes.None;

            queue.DefaultPropertiesToSend.UseJournalQueue = false;

        }

        /// <summary>

        /// Derived classes may call this from their own Send methods that

        /// accept meaningful objects.

        /// </summary>

        public virtual void Send(object msg) {

            queue.Send(msg, transactionType);

        }

 

        public virtual object Receive()

        {

            try

            {

 

                using (Message message = queue.Receive(timeout, transactionType))

                    return message;

            }

            catch (MessageQueueException mqex)

            {

                if (mqex.MessageQueueErrorCode == MessageQueueErrorCode.IOTimeout)

                    throw new TimeoutException();

 

                throw;

            }

        }

 

        #region IDisposable Members

        public void Dispose() {

            queue.Dispose();

        }

        #endregion

    }

}

 

3>MessageRecorder

 

 

 

using System;

using System.Configuration;

using System.Messaging;

namespace MsmqDemo

{

 

    /// <summary>

    /// This class is an implementation for sending and receiving orders to and from MSMQ

    /// </summary>

    public class MsgRecorder : PetShopQueue, IRecorder {

 

        // Path example - FormatName:DIRECT=OS:MyMachineName\Private$\OrderQueueName

        private static readonly string queuePath = ConfigurationManager.AppSettings["MessageQueuePath"];

        private static int queueTimeout = 20;

 

        public MsgRecorder() : base(queuePath, queueTimeout)

        {

            Type[] t = new Type[] {typeof(MessageBase) };

            queue.Formatter = new XmlMessageFormatter(t);

        }

 

 

        /// <summary>

        /// Method to retrieve  MessageBase from  Message Queue

        /// </summary>

        /// <returns>All information for an MessageBase</returns>

        public new MessageBase Receive()

        {

            // This method involves in distributed transaction and need Automatic Transaction type

            base.transactionType = MessageQueueTransactionType.Automatic;

            return (MessageBase)((Message)base.Receive()).Body;

        }

        public MessageBase Receive(int timeout)

        {

            base.timeout = TimeSpan.FromSeconds(Convert.ToDouble(timeout));

            return Receive();//base.Receive();base.timeout

        }

 

        /// <summary>

        /// Method to send asynchronous order to  Message Queue

        /// </summary>

        /// <param name="orderMessage">All information for an MessageBase</param>

        public void Send(MessageBase msg)

        {

            // This method does not involve in distributed transaction and optimizes performance using Single type

            base.transactionType = MessageQueueTransactionType.Single;

            base.Send(msg);

        }

    }

}

 

 

>4 工厂

using System;

using System.Collections.Generic;

using System.Text;

using System.Reflection;

using System.Configuration;

using System.Messaging;

 

namespace MsmqDemo

{

    public sealed class DataAccess

    {

        private static readonly string recorderPath = ConfigurationManager.AppSettings["RecorderDAL"];

        /// <summary>

        /// 创建记录器

        /// </summary>

        /// <returns></returns>

        public static IRecorder CreateRecorder()

        {

            string className = recorderPath + ".MsgRecorder";

            return (IRecorder)Assembly.Load(recorderPath).CreateInstance(className);

        }

 

 

 

 

 

 

 

 

 

 

 

 

消息的发送、接受器的代码已经贴完,先写到这里,待续。。。

posted @ 2008-11-10 15:28  roboth  阅读(1221)  评论(2编辑  收藏  举报