RabbitMQ心跳检测与掉线重连

1、RabbitMQListener,自定义消息监听器

using RabbitMQ.Client;
using RabbitMQ.Client.Events;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using RabbitMQ.Client.Exceptions;

namespace MQ_Receive
{
    /// <summary>
    /// RabbitMq消息监听器
    /// </summary>
    public class RabbitMqListener
    {
        private ConnectionFactory _factory;
        private IConnection _con;
        private IModel _channel;
        private EventingBasicConsumer _consumer;

        private readonly string _rabbitMqUri;
        private readonly string _exchangeType;
        private readonly string _exchangeName;
        private readonly string _queueName;
        private readonly string _routeKey;
        private Func<string, bool> _messageHandler;

        /// <summary>
        /// RabbitMQ消息监听器,若指定的队列不存在,则自动创建队列。并在消息交换机上绑定指定的消息路由规则(路由key)
        /// </summary>
        /// <param name="rabbitMqUri">连接串,如 amqp://guest:guest@localhost:5672/</param>
        /// <param name="exchangeName">消息交换机</param>
        /// <param name="exchangeType">交换机类型,如 ExchangeType.Direct</param>
        /// <param name="queueName">要监听的队列</param>
        /// <param name="routeKey">消息路由key</param>
        public RabbitMqListener(string rabbitMqUri, string exchangeName, string exchangeType, string queueName, string routeKey = "")
        {
            this._rabbitMqUri = rabbitMqUri;
            this._exchangeName = exchangeName;
            this._exchangeType = exchangeType;
            this._queueName = queueName;
            this._routeKey = routeKey;
        }

        /// <summary>
        /// 创建连接
        /// </summary>
        private void CreateConnection()
        {
            _factory = new ConnectionFactory
            {
                Uri = new Uri(_rabbitMqUri),
                RequestedHeartbeat = 20,
                AutomaticRecoveryEnabled = true,
                TopologyRecoveryEnabled = true,
                NetworkRecoveryInterval = TimeSpan.FromSeconds(10)
            };

            _con = _factory.CreateConnection();
            _con.ConnectionShutdown += (_sender, _e) => ReMessageListen();//掉线重新连接并监听队列消息
        }

        /// <summary>
        /// 创建信道
        /// </summary>
        private void CreateChannel()
        {
            _channel = _con.CreateModel();
            _channel.ExchangeDeclare(_exchangeName, _exchangeType, true, false, null);
            _channel.QueueDeclare(_queueName, true, false, false, null); //创建一个消息队列,用来存储消息
            _channel.QueueBind(_queueName, _exchangeName, _routeKey, null);
            _channel.BasicQos(0, 3, true); //在非自动确认消息的前提下,如果一定数目的消息(通过基于consume或者channel设置Qos的值)未被确认前,不进行消费新的消息
        }

        /// <summary>
        /// 监听队列消息
        /// </summary>
        /// <param name="messageHandler">消息处理器,当监测到队列消息时回调该处理器</param>
        /// <returns>监听状态</returns>
        public bool MessageListen(Func<string, bool> messageHandler)
        {
            try
            {
                this.CreateConnection();
                this.CreateChannel();

                _consumer = new EventingBasicConsumer(_channel); //基于事件的消息推送方式
                _consumer.Received += (_sender, _e) =>
                {
                    string msg = Encoding.UTF8.GetString(_e.Body);
                    if (messageHandler != null)
                    {
                        this._messageHandler = messageHandler;
                        try
                        {
                            var isOk = this._messageHandler(msg);
                            if (isOk)
                            {
                                _channel.BasicAck(_e.DeliveryTag, false);
                            }
                        }
                        catch (Exception ex)
                        {
                            LoggerManager.ErrorLog.Error("消息处理器执行异常:" + ex.Message, ex);
                        } 
                    }
                };

                _channel.BasicConsume(_queueName, false, _consumer); //手动确认
                return true;
            }
            catch (Exception ex)
            {
                LoggerManager.ErrorLog.Error("尝试监听队列消息出现错误:" + ex.Message, ex);
            }
            return false;
        }

        public void ReMessageListen()
        {
            try
            {
                //清除连接及频道
                CleanupResource();

                var mres = new ManualResetEventSlim(false); //初始化状态为false
                while (!mres.Wait(3000)) //每3秒监测一次状态,直到状态为true
                {
                    if (MessageListen(_messageHandler))
                    {
                        mres.Set(); //设置状态为true并跳出循环
                    }
                }
            }
            catch (Exception ex)
            {
                LoggerManager.ErrorLog.Error("尝试连接RabbitMQ服务器出现错误:" + ex.Message, ex);
            }
        }

        /// <summary>
        /// 清理资源
        /// </summary>
        private void CleanupResource()
        {
            if (_channel != null && _channel.IsOpen)
            {
                try
                {
                    _channel.Close();
                }
                catch (Exception ex)
                {
                    LoggerManager.ErrorLog.Error("尝试关闭RabbitMQ信道遇到错误", ex);
                }
                _channel = null;
            }

            if (_con != null && _con.IsOpen)
            {
                try
                {
                    _con.Close();
                }
                catch (Exception ex)
                {
                    LoggerManager.ErrorLog.Error("尝试关闭RabbitMQ连接遇到错误", ex);
                }
                _con = null;
            }
        }
    }
}

2、调用代码

using RabbitMQ.Client;
using RabbitMQ.Client.Events;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace MQ_Receive
{
    public partial class Form1 : Form
    {
        private delegate void ChangeText(string text);
        private readonly ChangeText _changeText;

        private static string rabbitHostUri = "amqp://guest:guest@localhost:5672/";
        private static string exchangeName = "order-exchange";
        private static string queueName = "order-message-test-queue";
        private static string routeKey = "order-message-routeKey";
        private static readonly object lockObj = new object();

        private static RabbitMQListener _listener;
        public static RabbitMQListener RabbitMQListener
        {
            get
            {
                if (_listener == null)
                {
                    lock (lockObj)
                    {
                        if (_listener == null)
                        {
                            _listener = new RabbitMQListener(rabbitHostUri, exchangeName, ExchangeType.Direct, queueName, routeKey);
                        }
                    }
                }

                return _listener;
            }
        }
        private Func<string, bool> MessageHandler
        {
            get {
                     return (msg) =>
                     {
                         this.label1.Invoke(_changeText, new object[1] { msg });
                         return true;
                     };
                }
        }

        public Form1()
        {
            InitializeComponent();
            this.label1.Text = "";
            this._changeText = SetText;
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            RabbitMQListener.MessageListen(MessageHandler);
        }

        private void SetText(string text)
        {
            this.label1.Text += text + "\n";
        }
    }
}

 

posted @ 2019-05-22 19:38  玻璃鱼儿  阅读(3674)  评论(0编辑  收藏  举报