• .NET ActiveMQ类库


    ActiveMQ .NET类库

    ActiveMQ是一种开源的,实现了JMS规范的,面向消息(MOM)的中间件,为应用程序提供高效的、可扩展的、稳定的和安全的企业级消息通信。

    0. 准备

    使用Nuget管理控制台安装最新版Apache.NMS.ActiveMQ

        PM> Install-Package Apache.NMS.ActiveMQ
    

    1. IMessageQueue 队列接口

        /// <summary>
        /// 消息队列接口
        /// </summary>
        public interface IMessageQueue
        {
    
            /// <summary>
            /// 打开连接
            /// </summary>
            void Open();
    
            /// <summary>
            /// 关闭连接
            /// </summary>
            void Close();
        }
    

    2. ActiveMQ 抽象基类

    /// <summary>
    /// ActiveMQ
    /// </summary>
    public abstract class ActiveMQ
    {
        #region 监听连接对象
        protected IConnection _connection;
        protected ISession _session;
        protected IMessageConsumer _consumer;
        #endregion
    
        /// <summary>
        /// 连接地址
        /// </summary>
        public string BrokerUri { get; set; }
    
        /// <summary>
        /// 用于登录的用户名,必须和密码同时指定
        /// </summary>
        public string UserName { get; set; }
    
        /// <summary>
        /// 用于登录的密码,必须和用户名同时指定
        /// </summary>
        public string Password { get; set; }
    
        /// <summary>
        /// 队列名称
        /// </summary>
        public string QueueName { get; set; }
    
        /// <summary>
        /// 指定使用队列的模式
        /// </summary>
        public MQMode MQMode { get; set; }
    }
    

    队列模式:

    /// <summary>
    /// 队列模式
    /// </summary>
    public enum MQMode
    {
        /// <summary>
        /// 队列,点对点模式。
        /// 使用此模式。一个生产者向队列存入一条消息之后,只有一个消费者能触发消息接收事件。
        /// </summary>
        Queue,
    
        /// <summary>
        /// 主题,发布者/订阅模式。
        /// 使用此模式,一个生产者向队列存入一条消息之后,所有订阅当前的主题的消费者都能触发消息接收事件。
        /// 使用此模式,必须先创建消费者,再创建生产者。
        /// </summary>
        Topic
    }
    

    3. ActiveMQProducer 生产者

    /// <summary>
    /// ActiveMQ生产者,打开连接,向指定队列中发送数据
    /// </summary>
    public class ActiveMQProducer : ActiveMQ, IMessageQueue, IDisposable
    {
        /// <summary>
        /// 队列缓存字典
        /// </summary>
        private ConcurrentDictionary<string, IMessageProducer> _concrtProcuder = new ConcurrentDictionary<string, IMessageProducer>();
    
        /// <summary>
        /// 打开连接
        /// </summary>
        public void Open()
        {
            if (string.IsNullOrWhiteSpace(this.BrokerUri))
                throw new MemberAccessException("未指定BrokerUri");
            if (string.IsNullOrWhiteSpace(this.QueueName))
                throw new MemberAccessException("未指定QueueName");
    
            var factory = new ConnectionFactory(this.BrokerUri);
            if (string.IsNullOrWhiteSpace(this.UserName) && string.IsNullOrWhiteSpace(this.Password))
                _connection = factory.CreateConnection();
            else
                _connection = factory.CreateConnection(this.UserName, this.Password);
            _connection.Start();
            _session = _connection.CreateSession();
    
            CreateProducer(this.QueueName);
        }
    
    
        /// <summary>
        /// 关闭连接
        /// </summary>
        public void Close()
        {
            IMessageProducer _p = null;
            foreach (var p in this._concrtProcuder)
            {
                if (this._concrtProcuder.TryGetValue(p.Key, out _p))
                {
                    _p?.Close();
                }
            }
            this._concrtProcuder.Clear();
    
            _session?.Close();
            _connection?.Close();
        }
    
        /// <summary>
        /// 向队列发送数据
        /// </summary>
        /// <typeparam name="T">数据类型</typeparam>
        /// <param name="body">数据</param>
        public void Put<T>(T body)
        {
            Send(this.QueueName, body);
        }
    
        /// <summary>
        /// 向指定队列发送数据
        /// </summary>
        /// <typeparam name="T">数据类型</typeparam>
        /// <param name="body">数据</param>
        /// <param name="queueName">指定队列名</param>
        public void Put<T>(T body, string queueName)
        {
            Send(queueName, body);
        }
    
        /// <summary>
        /// 创建队列
        /// </summary>
        /// <param name="queueName"></param>
        private IMessageProducer CreateProducer(string queueName)
        {
            if (_session == null)
            {
                Open();
            }
    
            //创建新生产者
            Func<string, IMessageProducer> CreateNewProducter = (name) =>
            {
                IMessageProducer _newProducer = null;
                switch (MQMode)
                {
                    case MQMode.Queue:
                        {
                            _newProducer = _session.CreateProducer(new ActiveMQQueue(name));
                            break;
                        }
                    case MQMode.Topic:
                        {
                            _newProducer = _session.CreateProducer(new ActiveMQTopic(name));
                            break;
                        }
                    default:
                        {
                            throw new Exception(string.Format("无法识别的MQMode类型:{0}", MQMode.ToString()));
                        }
                }
                return _newProducer;
            };
    
            return this._concrtProcuder.GetOrAdd(queueName, CreateNewProducter);
        }
    
        /// <summary>
        /// 发送数据
        /// </summary>
        /// <param name="queueName">队列名称</param>
        /// <typeparam name="T"></typeparam>
        /// <param name="body">数据</param>
        private void Send<T>(string queueName, T body)
        {
            var producer = CreateProducer(queueName);
            IMessage msg;
            if (body is byte[])
            {
                msg = producer.CreateBytesMessage(body as byte[]);
            }
            else if (body is string)
            {
                msg = producer.CreateTextMessage(body as string);
            }
            else
            {
                msg = producer.CreateObjectMessage(body);
            }
            if (msg != null)
            {
                producer.Send(msg, MsgDeliveryMode.Persistent, MsgPriority.Normal, TimeSpan.MinValue);
            }
        }
    
        /// <summary>
        /// 执行与释放或重置非托管资源相关的应用程序定义的任务。
        /// </summary>
        public void Dispose()
        {
            this.Close();
        }
    }
    

    4. ActiveMQConsumer 消费者

    /// <summary>
    /// ActiveMQ消费者,打开连接,监听队列,接收到数据之后触发回调
    /// </summary>
    public class ActiveMQConsumer : ActiveMQ, IMessageQueue, IDisposable
    {
        /// <summary>
        /// 接收到数据回调,ActiveMQ原生IMessage类型
        /// </summary>
        public Action<IMessage> OnMessageReceived { get; set; }
    
        /// <summary>
        /// 接收到消息回调(业务数据对象, 根据自己的业务灵活替换)
        /// </summary>
        public Action<DataCenterMessage> OnDataCenterMessageReceived { get; set; }
    
        /// <summary>
        /// 打开连接
        /// </summary>
        public void Open()
        {
            if (string.IsNullOrWhiteSpace(this.BrokerUri))
                throw new MemberAccessException("未指定BrokerUri");
            if (string.IsNullOrWhiteSpace(this.QueueName))
                throw new MemberAccessException("未指定QueueName");
    
            var factory = new ConnectionFactory(this.BrokerUri);
            if (string.IsNullOrWhiteSpace(this.UserName) && string.IsNullOrWhiteSpace(this.Password))
                _connection = factory.CreateConnection();
            else
                _connection = factory.CreateConnection(this.UserName, this.Password);
            _connection.Start();
            _session = _connection.CreateSession(AcknowledgementMode.AutoAcknowledge);
    
            switch (MQMode)
            {
                case MQMode.Queue:
                    {
                        _consumer = _session.CreateConsumer(new ActiveMQQueue(this.QueueName));
                        break;
                    }
                case MQMode.Topic:
                    {
                        _consumer = _session.CreateConsumer(new ActiveMQTopic(this.QueueName));
                        break;
                    }
                default:
                    {
                        throw new Exception(string.Format("无法识别的MQMode类型:{0}", MQMode.ToString()));
                    }
            }
        }
    
        /// <summary>
        /// 关闭连接
        /// </summary>
        public void Close()
        {
            _consumer?.Close();
            _session?.Close();
            _connection?.Close();
        }
    
        /// <summary>
        /// 开始监听
        /// </summary>
        public void StartListen()
        {
            if (_consumer == null)
            {
                Open();
            }
    
            _consumer.Listener += new MessageListener(msg =>
            {
                if (OnMessageReceived != null)
                    OnMessageReceived(msg);
    
                //转换为业务需要的数据对象
                if (OnDataCenterMessageReceived != null)
                {
                    var objectMessage = msg as ActiveMQObjectMessage;
                    if (objectMessage != null)
                    {
                        var dataCenterMsg = objectMessage.Body as DataCenterMessage;
                        if (dataCenterMsg != null)
                        {
                            OnDataCenterMessageReceived(dataCenterMsg);
                        }
                    }
                }
            });
        }
    
        /// <summary>
        /// 执行与释放或重置非托管资源相关的应用程序定义的任务。
        /// </summary>
        public void Dispose()
        {
            this.Close();
        }
    }
    

    5. 扩展方法

    /// <summary>
    /// 扩展方法类
    /// </summary>
    public static class ExtendMethods
    {
        /// <summary>
        /// 将对象转换为bytes
        /// </summary>
        /// <param name="obj"></param>
        /// <returns>bytes</returns>
        public static byte[] ToBytes<T>(this T obj) where T : class
        {
            if (obj == null)
                return null;
            using (var ms = new MemoryStream())
            {
                var formatter = new BinaryFormatter();
                formatter.Serialize(ms, obj);
                return ms.GetBuffer();
            }
        }
    
        /// <summary>
        /// 将bytes转换为对象
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="bytes"></param>
        /// <returns></returns>
        public static T ToObject<T>(this byte[] bytes) where T : class
        {
            if (bytes == null)
                return default(T);
            using (var ms = new MemoryStream(bytes))
            {
                var formatter = new BinaryFormatter();
                return formatter.Deserialize(ms) as T;
            }
        }
    }
    

    6. 使用示例:

            #region 生产者
            var producer = new ActiveMQProducer();
            producer.BrokerUri = @"tcp://127.0.0.1:61616/";
            producer.UserName = "admin";
            producer.Password = "admin";
            producer.QueueName = "TestQueueName";
            producer.MQMode = MQMode.Queue;
    
            producer.Open();
            var message = new DataCenterMessage()
            {
                //初始化业务数据对象...
            };
    
            //发送到队列, Put对象类必须使用[Serializable]注解属性
            producer.Put(message);
            #endregion
    
            #region 消费者
            var consumer = new ActiveMQConsumer();
            consumer.BrokerUri = @"tcp://127.0.0.1:61616/";
            consumer.UserName = "admin";
            consumer.Password = "admin";
            consumer.QueueName = "TestQueueName";
            consumer.MQMode = MQMode.Queue;
    
            consumer.OnMessageReceived = (msg) =>
            {
                var bytesMessage = msg as ActiveMQBytesMessage;
                if (bytesMessage != null)
                {
                    var buffer = new byte[bytesMessage.BodyLength];
                    bytesMessage.WriteBytes(buffer);
                    var result = buffer.ToObject<DataCenterMessage>();
                    Debug.WriteLine(result);
                }
            };
    
            consumer.OnDataCenterMessageReceived = (msg) =>
            {
                Debug.Write(msg);
            };
    
            consumer.Open();
            consumer.StartListen();
  • 相关阅读:
    优先级管理器 IPriorityManager -- ESBasic 可复用的.NET类库(14)
    对象获取器IObjectRetriever -- ESBasic 可复用的.NET类库(17)
    定时刷新缓存管理器 IRefreshableCacheManager --ESBasic 可复用的.NET类库(16)
    TopN排行榜容器 TopNOrderedContainer -- ESBasic 可复用的.NET类库(20)
    回调定时器ICallbackTimer --ESBasic 可复用的.NET类库(07)
    Linux kernel data types, alignment, compat_ioctl 数据类型,对齐问题和compat_ioctl
    ubnutu开启daytime服务
    从长春到深圳“一个人的旅行”第二篇
    多客户模式

  • 原文地址:https://www.cnblogs.com/aning2015/p/7659957.html
Copyright © 2020-2023  润新知