/// <summary> /// 注册消息处理器 /// </summary> /// <typeparam name="TMessage">消息类型</typeparam> /// <typeparam name="THandler">消息处理器类型</typeparam> /// <param name="redeliveryCheck">是否开启重发确认;如果消息处理器逻辑已经实现为幂等则不需要开启以便节省计算资源,否则请打开该选项</param> public void RegisterDirectHandler <TMessage, THandler>(string exchangeName = "", string queueName = "", string routeKey = "") where THandler : BaseHandleMessages <TMessage> where TMessage : BaseMessage { 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) && !string.IsNullOrEmpty(routeKey)) { exchange = exchangeName; queue = queueName; EnsureQueue.DirectEnsureQueue(channel, ref exchange, ref queue, routeKey); } else { EnsureQueue.DirectEnsureQueue(channel, type, out exchange, out queue); } channel.BasicConsume(queue, false, consumer); } catch (Exception ex) { _logger.Debug("RegisterHandler()出错,异常:" + ex.Message + ";堆栈:" + ex.StackTrace); } }
private static bool SendDirect(BaseMessage message, int delaySend = 0) { if (string.IsNullOrWhiteSpace(message.Source)) { throw new ArgumentNullException("message.Source"); } if (!PrePersistMessage(message)) { return(false); } var messageType = message.GetType(); delaySend = delaySend == 0 ? delaySend : Math.Max(delaySend, 5000); // 至少保证5秒的延迟,否则意义不大 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) && !string.IsNullOrEmpty(message.routeKey)) { exchange = message.exchangeName; queue = message.queueName; EnsureQueue.DirectEnsureQueue(channel, ref exchange, ref queue, message.routeKey, delaySend); } else { EnsureQueue.DirectEnsureQueue(channel, messageType, out exchange, out queue, delaySend); } var route_key = queue; 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, route_key, 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; direct_queue.Enqueue(message); return(true); } throw new Exception("数据库update出现异常"); } throw new Exception($"消息发送超过最大重试次数({default_retry_count}次)"); } } return(true); }