/// <summary> /// 发送消息 /// </summary> /// <param name="message">消息</param> /// <param name="routingKey">路由key</param> /// <returns></returns> public SendResult SendMessage(Message message, string routingKey) { if (_isRunning == 0) { return(new SendResult(SendStatus.Failed, null, "Couldn't send message when is not running.")); } if (message == null) { return(new SendResult(SendStatus.Failed, null, "Message is null.")); } if (!_topics.ContainsKey(message.Topic)) { return(new SendResult(SendStatus.Failed, null, $"Topic {message.Topic} not registered.")); } IRabbitMQChannel channel = null; try { var queueCount = _topics[message.Topic]; var queueId = string.IsNullOrEmpty(routingKey) ? 0 : (Crc16.GetHashCode(routingKey) % queueCount); var messageId = Guid.NewGuid().ToString(); var createdTime = message.CreatedTime == DateTime.MinValue ? DateTime.Now : message.CreatedTime; if (_channelPool.TryDequeue(out Tuple <DateTime, IRabbitMQChannel> item)) { channel = item.Item2; } else { channel = _amqpConnection.CreateModel(); channel.ConfirmSelect(); } var properties = channel.CreateBasicProperties(); properties.Persistent = true; properties.ContentType = message.ContentType ?? string.Empty; properties.MessageId = Guid.NewGuid().ToString(); properties.Type = message.Tag ?? string.Empty; properties.Timestamp = new AmqpTimestamp(DateTime2UnixTime.ToUnixTime(createdTime)); if (_delayedMessageEnabled && message.DelayedMilliseconds > 0) { properties.Headers = new Dictionary <string, object> { { "x-delay", message.DelayedMilliseconds } }; } channel.BasicPublish(exchange: _delayedMessageEnabled && message.DelayedMilliseconds > 0 ? $"{message.Topic}-delayed" : message.Topic, routingKey: queueId.ToString(), mandatory: true, basicProperties: properties, body: message.Body); if (!channel.WaitForConfirms(_sendMsgTimeout, out bool timedOut)) { return(new SendResult(timedOut ? SendStatus.Timeout : SendStatus.Failed, null, "Wait for confirms failed.")); } var storeResult = new MessageStoreResult(messageId, message.Code, message.Topic, queueId, createdTime, message.Tag); return(new SendResult(SendStatus.Success, storeResult, null)); } catch (Exception ex) { throw new System.IO.IOException("Send message has exception.", ex); } finally { if (channel != null) { _channelPool.Enqueue(new Tuple <DateTime, IRabbitMQChannel>(DateTime.Now, channel)); } } }