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; namespace MQ_Receive { public class RabbitMQListener { private ConnectionFactory _factory; private IConnection _con; private IModel _channel; private EventingBasicConsumer _consumer; private string _rabbitMQUri; private string _exchangeType; private string _exchangeName; private string _queueName; private string _routeKey; private Func<string, bool> _messageHandler; /// <summary> /// RabbitMQ消息监听器 /// </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"></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(); _factory.Uri = new Uri(_rabbitMQUri); _factory.RequestedHeartbeat = 20; _factory.AutomaticRecoveryEnabled = true; _factory.TopologyRecoveryEnabled = true; _factory.NetworkRecoveryInterval = TimeSpan.FromSeconds(10); _con = _factory.CreateConnection(); _con.ConnectionShutdown += con_ConnectionShutdown; } /// <summary> /// 创建信道 /// </summary> private void CreateChannel() { _channel = _con.CreateModel(); _channel.ExchangeDeclare(_exchangeName, ExchangeType.Direct, 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> public void 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; var isOk = this._messageHandler(msg); if (isOk) { _channel.BasicAck(_e.DeliveryTag, false); } } }; _channel.BasicConsume(_queueName, false, _consumer); //手动确认 } catch (RabbitMQ.Client.Exceptions.BrokerUnreachableException e) { throw e; } catch (Exception ex) { throw ex; } } /// <summary> /// 掉线重新连接并监听队列消息 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void con_ConnectionShutdown(object sender, ShutdownEventArgs e) { ReMessageListen(); } public void ReMessageListen() { try { //清除连接及频道 Cleanup(); var mres = new ManualResetEventSlim(false); // state is initially false while (!mres.Wait(3000)) // loop until state is true, checking every 3s { try { MessageListen(_messageHandler); mres.Set(); // state set to true - breaks out of loop } catch (Exception ex) { //LogHandler.WriteLog("RabbitMQ尝试连接RabbitMQ服务器出现错误:" + ex.Message, ex); } } } catch (Exception ex) { //LogHandler.WriteLog("RabbitMQ尝试重新连接RabbitMQ服务器出现错误:" + ex.Message, ex); } } /// <summary> /// 释放资源 /// </summary> private void Cleanup() { try { if (_channel != null && _channel.IsOpen) { try { _channel.Close(); } catch (Exception ex) { //LogHandler.WriteLog("RabbitMQ重新连接,正在尝试关闭之前的Channel[发送],但遇到错误", ex); } _channel = null; } if (_con != null && _con.IsOpen) { try { _con.Close(); } catch (Exception ex) { //LogHandler.WriteLog("RabbitMQ重新连接,正在尝试关闭之前的连接,但遇到错误", ex); } _con = null; } } catch (IOException ex) { throw ex; } } } }
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"; } } }