/// <summary> /// 注册消息处理器,根据模式匹配接收消息 /// </summary> /// <typeparam name="TMessage">消息类型</typeparam> /// <typeparam name="THandler">消息处理器类型</typeparam> /// <param name="subscriberName">订阅器的名称</param> /// <param name="redeliveryCheck">是否开启重发确认;如果消息处理器逻辑已经实现为幂等则不需要开启以便节省计算资源,否则请打开该选项</param> /// <param name="subscribePatterns">订阅器支持的消息模式</param> public void RegisterTopicHandler <TMessage, THandler>(string routeKey, string exchangeName = "", string queueName = "") where THandler : BaseHandleMessages <TMessage> where TMessage : BaseMessage { if (string.IsNullOrWhiteSpace(routeKey)) { throw new ArgumentNullException("routeKey"); } try { var type = typeof(TMessage); var handler = Activator.CreateInstance <THandler>(); var channel = connection.CreateModel(); var consumer = new EventingBasicConsumer(channel); /* * @param prefetchSize maximum amount of content (measured in octets) that the server will deliver, 0 if unlimited * @param prefetchCount maximum number of messages that the server will deliver, 0 if unlimited * @param global true if the settings should be applied to the entire channel rather than each consumer */ channel.BasicQos(0, prefetch_count, false); consumer.Received += async(model, ea) => { var json = Encoding.UTF8.GetString(ea.Body); var msg = JsonConvert.DeserializeObject <TMessage>(json); await handler.Handle(msg); if (msg.NeedNAck) { channel.BasicNack(ea.DeliveryTag, false, true); } else { channel.BasicAck(ea.DeliveryTag, false); } }; var exchange = string.Empty; var queue = string.Empty; if (!string.IsNullOrEmpty(exchangeName) && !string.IsNullOrEmpty(queueName)) { exchange = exchangeName; queue = queueName; EnsureQueue.TopicEnsureQueue(channel, routeKey, ref exchange, ref queue); } else { EnsureQueue.TopicEnsureQueue(channel, type, routeKey, out exchange, out queue); } channel.BasicConsume(queue, false, consumer); } catch (Exception ex) { _logger.Debug("RegisterTopicHandler出错,异常:" + ex.Message + ";堆栈:" + ex.StackTrace); } }
private static bool SendTopic(BaseMessage message, int delaySend = 0) { if (string.IsNullOrWhiteSpace(message.Source)) { throw new ArgumentNullException("message.Source"); } if (string.IsNullOrWhiteSpace(message.routeKey)) { throw new ArgumentNullException("routeKey"); } if (!PrePersistMessage(message)) { return(false); } var messageType = message.GetType(); delaySend = delaySend == 0 ? delaySend : Math.Max(delaySend, 1000); // 至少保证1秒的延迟,否则意义不大 using (var pooled = InnerCreateChannel(messageType)) { IModel channel = pooled.Channel; pooled.PreRecord(message.MsgHash); var exchange = string.Empty; var queue = string.Empty; if (!string.IsNullOrEmpty(message.exchangeName) && !string.IsNullOrEmpty(message.queueName)) { exchange = message.exchangeName; queue = message.queueName; EnsureQueue.TopicEnsureQueue(channel, message.routeKey, ref exchange, ref queue, delaySend); } else { EnsureQueue.TopicEnsureQueue(channel, messageType, message.routeKey, out exchange, out queue, delaySend); } var json = JsonConvert.SerializeObject(message); var bytes = Encoding.UTF8.GetBytes(json); var props = channel.CreateBasicProperties(); props.ContentType = "text/plain"; props.DeliveryMode = 2; channel.BasicPublish(exchange, message.routeKey, props, bytes); var time_out = Math.Max(default_retry_wait, message.RetryCount_Publish * 2 /*2倍往上扩大,防止出现均等*/ * 1000); var ret = channel.WaitForConfirms(TimeSpan.FromMilliseconds(time_out)); if (!ret) { if (message.RetryCount_Publish < default_retry_count) { var ok = _message_queue_helper.Update( message.MsgHash, fromStatus1: MsgStatus.Created, // 之前的状态只能是1 Created 或者2 Retry fromStatus2: MsgStatus.Retrying, toStatus: MsgStatus.Retrying); if (ok) { message.RetryCount_Publish += 1; message.LastRetryTime = DateTime.Now; topic_queue.Enqueue(message); return(true); } throw new Exception("数据库update出现异常"); } throw new Exception($"消息发送超过最大重试次数({default_retry_count}次)"); } } return(true); }