/// <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));
                }
            }
        }