public void Subscribe(Type eventType, Type eventHandleType, string type = ExchangeType.Topic) { object attribute = eventType.GetCustomAttributes(typeof(EventBusAttribute), true).FirstOrDefault(); if (attribute is EventBusAttribute attr) { string queue = attr.Queue ?? $"{ attr.Exchange }.{ eventType.Name }"; if (!_persistentConnection.IsConnected) { _persistentConnection.TryConnect(); } IModel channel; #region snippet try { channel = _persistentConnection.ExchangeDeclare(exchange: attr.Exchange, type: type); channel.QueueDeclarePassive(queue); } catch { channel = _persistentConnection.ExchangeDeclare(exchange: attr.Exchange, type: type); channel.QueueDeclare(queue: queue, durable: true, exclusive: false, autoDelete: false, arguments: null); } #endregion channel.QueueBind(queue, attr.Exchange, attr.RoutingKey, null); channel.BasicQos(0, 1, false); EventingBasicConsumer consumer = new EventingBasicConsumer(channel); consumer.Received += async(model, ea) => { string body = Encoding.UTF8.GetString(ea.Body); bool isAck = false; try { await ProcessEvent(body, eventType, eventHandleType); channel.BasicAck(ea.DeliveryTag, multiple: false); isAck = true; } catch (Exception ex) { _logger.LogError(new EventId(ex.HResult), ex, ex.Message); await Task.Delay((int)_persistentConnection.Configuration.ConsumerFailRetryInterval.TotalMilliseconds).ContinueWith(p => channel.BasicNack(ea.DeliveryTag, false, true)); } finally { _eventHandlerFactory?.SubscribeEvent(new EventBusArgs(_persistentConnection.Endpoint, ea.Exchange, queue, attr.RoutingKey, type, _persistentConnection.Configuration.ClientProvidedName, body)); _logger.Information($"RabbitMQEventBus\t{DateTimeOffset.Now.ToString("yyyy-MM-dd HH:mm:ss")}\t{isAck}\t{ea.Exchange}\t{ea.RoutingKey}\t{body}"); } }; channel.CallbackException += (sender, ex) => { }; channel.BasicConsume(queue: queue, autoAck: false, consumer: consumer); } }
public void Subscribe(Type eventType, string type = ExchangeType.Topic) { var attributes = eventType.GetCustomAttributes(typeof(EventBusAttribute), true); var millisecondsDelay = (int?)_persistentConnection?.Configuration?.ConsumerFailRetryInterval.TotalMilliseconds ?? 1000; foreach (var attribute in attributes) { if (attribute is EventBusAttribute attr) { string queue = attr.Queue ?? (_persistentConnection.Configuration.Prefix == QueuePrefixType.ExchangeName ? $"{ attr.Exchange }.{ eventType.Name }" : $"{_persistentConnection.Configuration.ClientProvidedName}.{ eventType.Name }"); if (!_persistentConnection.IsConnected) { _persistentConnection.TryConnect(); } IModel channel; #region snippet var arguments = new Dictionary <string, object>(); #region 死信队列设置 if (_persistentConnection.Configuration.DeadLetterExchange.Enabled) { string deadExchangeName = $"{_persistentConnection.Configuration.DeadLetterExchange.ExchangeNamePrefix}{_persistentConnection.Configuration.DeadLetterExchange.CustomizeExchangeName ?? attr.Exchange}{_persistentConnection.Configuration.DeadLetterExchange.ExchangeNameSuffix}"; string deadQueueName = $"{_persistentConnection.Configuration.DeadLetterExchange.ExchangeNamePrefix}{queue}{_persistentConnection.Configuration.DeadLetterExchange.ExchangeNameSuffix}"; IModel dlxChannel; try { dlxChannel = _persistentConnection.ExchangeDeclare(exchange: deadExchangeName, type: type); dlxChannel.QueueDeclarePassive(deadQueueName); } catch { dlxChannel = _persistentConnection.ExchangeDeclare(exchange: deadExchangeName, type: type); dlxChannel.QueueDeclare(queue: deadQueueName, durable: true, exclusive: false, autoDelete: false, arguments: null); } dlxChannel.QueueBind(deadQueueName, deadExchangeName, attr.RoutingKey, null); arguments.Add("x-dead-letter-exchange", deadExchangeName); } #endregion try { channel = _persistentConnection.ExchangeDeclare(exchange: attr.Exchange, type: type); channel.QueueDeclarePassive(queue); } catch { channel = _persistentConnection.ExchangeDeclare(exchange: attr.Exchange, type: type); if (_persistentConnection.Configuration.MessageTTL != null && _persistentConnection.Configuration.MessageTTL > 0) { arguments.Add("x-message-ttl", _persistentConnection.Configuration.MessageTTL); } channel.QueueDeclare(queue: queue, durable: true, exclusive: false, autoDelete: false, arguments: arguments); } #endregion channel.QueueBind(queue, attr.Exchange, attr.RoutingKey, null); channel.BasicQos(0, _persistentConnection.Configuration.PrefetchCount, false); EventingBasicConsumer consumer = new EventingBasicConsumer(channel); consumer.Received += async(model, ea) => { string body = Encoding.UTF8.GetString(ea.Body.ToArray()); bool isAck = false; try { await ProcessEvent(body, eventType, ea); //不确定是否需要改变Multiple是否需要改为true channel.BasicAck(ea.DeliveryTag, multiple: false); isAck = true; } catch (Exception ex) { _logger.LogError(new EventId(ex.HResult), ex, ex.Message); } finally { _eventHandlerFactory?.SubscribeEvent(new EventBusArgs(_persistentConnection.Endpoint, ea.Exchange, queue, attr.RoutingKey, type, _persistentConnection.Configuration.ClientProvidedName, body, isAck)); _logger.WriteLog(_persistentConnection.Configuration.Level, $"{DateTimeOffset.Now.ToString("yyyy-MM-dd HH:mm:ss")}\t{isAck}\t{ea.Exchange}\t{ea.RoutingKey}\t{body}"); if (!isAck) { await Task.Delay(millisecondsDelay); channel.BasicNack(ea.DeliveryTag, false, true); } } }; channel.CallbackException += (sender, ex) => { _logger.LogError(new EventId(ex.Exception.HResult), ex.Exception, ex.Exception.Message); }; channel.BasicConsume(queue: queue, autoAck: false, consumer: consumer); } } }