/// <summary> /// 监听延迟队列,并使用回调函数处理 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="queue">队列名</param> /// <param name="callback">获得队列数据时的回调函数</param> /// <param name="errorCallback">获取并处理队列数据出现异常时的回调函数</param> public void DelayWaitQueue <T>(string queue, QueueCallback <T> callback, QueueErrorCallback errorCallback = null) { if (string.IsNullOrEmpty(queue)) { throw new ArgumentException("队列名不能为空", nameof(queue)); } //var deadRoutingKey = queue + ".DeadRoute"; var deadQueue = queue + ".DeadLetter"; WaitQueue(deadQueue, callback, errorCallback); }
/// <summary> /// 监听队列,并使用回调函数处理 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="queue">队列名</param> /// <param name="consumerNum">启动几个消费者</param> /// <param name="callback">获得队列数据时的回调函数</param> /// <param name="errorCallback">获取并处理队列数据出现异常时的回调函数</param> /// <param name="prefetchCount">每个消费者的消息预取数量,默认5条,超过5个未ack时,不接收消息</param> /// <param name="useAsync">异步处理消息还是同步</param> public void WaitQueue <T>(string queue, int consumerNum, QueueCallback <T> callback, QueueErrorCallback errorCallback = null, ushort prefetchCount = 0, bool useAsync = false) { if (consumerNum < 1) { throw new ArgumentException("消费者数量不能小于1"); } for (var i = 0; i < consumerNum; i++) { WaitQueue(queue, callback, errorCallback, prefetchCount, useAsync); } }
/// <summary> /// 监听队列,并使用回调函数处理(不反序列化,带routekey) /// </summary> /// <param name="queue"></param> /// <param name="callback">参数1:数据, 参数2:路由, 参数3:header</param> /// <param name="errorCallback">异常回调方法</param> /// <param name="prefetchCount">预取消息数</param> /// <param name="useAsync">是否异步处理收到的消息</param> public void WaitQueueWithRouteKey(string queue, Action <string, string, IDictionary <string, object> > callback, QueueErrorCallback errorCallback = null, ushort prefetchCount = 0, bool useAsync = false) { if (string.IsNullOrEmpty(queue)) { throw new ArgumentException("队列名不能为空", nameof(queue)); } errorCallback = errorCallback ?? WaitErrorCallback; if (prefetchCount <= 0) { prefetchCount = WaitPrefetchCount; } try { // 要监听队列,所以不能关闭channel通道 var channel = GetChannel(); channel.BasicQos(0, prefetchCount, false); var consumer = new EventingBasicConsumer(channel); consumer.Received += (sender, e) => { void msgCallback(object nullobj) { try { ReceiveContext(e.BasicProperties.Headers); if (callback == null) { return; } callback(Utf8.GetString(e.Body), e.RoutingKey, e.BasicProperties.Headers); } catch (Exception exp) { if (errorCallback == null) { throw; } errorCallback(exp); //Console.WriteLine("队列接收处理出错:" + exp.ToString()); } finally { try { // 手工ack 参数2:multiple:是否批量.true:将一次性ack所有小于deliveryTag的消息 ((EventingBasicConsumer)sender).Model.BasicAck(e.DeliveryTag, false); } catch (Exception ackExp) { if (errorCallback == null) { throw; } errorCallback(ackExp); } finally { NLogHelper.Default.Debug($"Event Received. Queue:{queue},Message:{Utf8.GetString(e.Body)}"); } } } if (useAsync) { ThreadPool.UnsafeQueueUserWorkItem(msgCallback, null); } else { msgCallback(null); } }; // 开启acknowledge机制,在接收事件里ack,配合qos进行流控 channel.BasicConsume(queue, false, consumer); } catch (Exception exp) { if (errorCallback == null) { throw; } errorCallback(exp); //Console.WriteLine("队列接收处理出错:" + exp.ToString()); } }
///// <summary> ///// 监听队列,并使用回调函数处理 ///// </summary> ///// <param name="queue">队列名</param> ///// <param name="callback">获得队列数据时的回调函数</param> ///// <param name="errorCallback">获取并处理队列数据出现异常时的回调函数</param> //[Obsolete("请改用WaitQueue<T>方法")] //public void WaitQueue(string queue, // QueueCallback callback, QueueErrorCallback errorCallback = null) //{ // if (string.IsNullOrEmpty(queue)) // { // throw new ArgumentException("队列名不能为空", nameof(queue)); // } // errorCallback = errorCallback ?? WaitErrorCallback; // ThreadPool.UnsafeQueueUserWorkItem(state => // { // try // { // // 要监听队列,所以不能关闭channel通道 // var channel = GetChannel(); // var consumer = new EventingBasicConsumer(channel); // consumer.Received += (sender, e) => // { // try // { // callback?.Invoke(e.Body, e.BasicProperties.Headers); // } // catch (Exception exp) // { // if (errorCallback == null) // throw; // errorCallback(exp); // //Console.WriteLine("队列接收处理出错:" + exp.ToString()); // } // }; // channel.BasicConsume(queue, true, consumer); // } // catch (Exception exp) // { // if (errorCallback == null) // throw; // errorCallback(exp); // //Console.WriteLine("队列接收处理出错:" + exp.ToString()); // } // }, callback); //} /// <summary> /// 监听队列,并使用回调函数处理 /// </summary> /// <param name="queue">队列名</param> /// <param name="callback">获得队列数据时的回调函数</param> /// <param name="errorCallback">获取并处理队列数据出现异常时的回调函数</param> /// <param name="prefetchCount">消息预取数量,默认5条,超过5个未ack时,不接收消息</param> /// <param name="useAsync">异步处理消息还是同步</param> public void WaitQueue(string queue, QueueCallback <string> callback, QueueErrorCallback errorCallback = null, ushort prefetchCount = 0, bool useAsync = false) { WaitQueue <string>(queue, callback, errorCallback, prefetchCount, useAsync); }