private IModel CreateRetryConsumerChannel(string queueName, string routeKey, QueueConsumerMode type, bool bindConsumer) { if (!_rabbitMqClient.IsConnected) { _rabbitMqClient.TryConnect(); } IDictionary <String, Object> arguments = new Dictionary <String, Object>(); arguments.Add("x-dead-letter-exchange", $"{BROKER_NAME}@{QueueConsumerMode.Fail.ToString()}"); arguments.Add("x-message-ttl", _messageTTL); arguments.Add("x-dead-letter-routing-key", routeKey); var channel = _rabbitMqClient.CreateModel(); var retryQueueName = $"{queueName}@{type.ToString()}"; //定义交换机 channel.ExchangeDeclare(exchange: $"{BROKER_NAME}@{type.ToString()}", type: ExchangeType.Direct); //定义队列 channel.QueueDeclare(retryQueueName, true, false, false, arguments); var consumer = new EventingBasicConsumer(channel); consumer.Received += async(model, ea) => { var eventName = ea.RoutingKey; await ProcessEvent(eventName, ea.Body, type, ea.BasicProperties, bindConsumer); channel.BasicAck(ea.DeliveryTag, false); }; if (bindConsumer) { channel.BasicQos(0, 1, false); channel.BasicConsume(queue: retryQueueName, autoAck: false, consumer: consumer); } else { channel.Close(); } return(channel); }
private IModel CreateFailConsumerChannel(string queueName, QueueConsumerMode type, bool bindConsumer) { if (!_rabbitMqClient.IsConnected) { _rabbitMqClient.TryConnect(); } var channel = _rabbitMqClient.CreateModel(); channel.ExchangeDeclare(exchange: $"{BROKER_NAME}@{type.ToString()}", type: ExchangeType.Direct); var failQueueName = $"{queueName}@{type.ToString()}"; channel.QueueDeclare(failQueueName, true, false, false, null); var consumer = new EventingBasicConsumer(channel); consumer.Received += async(model, ea) => { var eventName = ea.RoutingKey; await ProcessEvent(eventName, ea.Body, type, ea.BasicProperties, bindConsumer); channel.BasicAck(ea.DeliveryTag, false); }; if (bindConsumer) { channel.BasicQos(0, 1, false); channel.BasicConsume(queue: failQueueName, autoAck: false, consumer: consumer); } else { channel.Close(); } return(channel); }
private async Task ProcessEvent(string eventName, byte[] body, QueueConsumerMode mode, IBasicProperties properties) { var message = Encoding.UTF8.GetString(body); if (_subsManager.HasSubscriptionsForEvent(eventName)) { var eventType = _subsManager.GetEventTypeByName(eventName); var integrationEvent = JsonConvert.DeserializeObject(message, eventType); var handlers = _subsManager.GetHandlersForEvent(eventName); var concreteType = typeof(IIntegrationEventHandler <>).MakeGenericType(eventType); foreach (var handlerfactory in handlers) { var handler = handlerfactory.DynamicInvoke(); long retryCount = 1; try { var fastInvoker = GetHandler($"{concreteType.FullName}.Handle", concreteType.GetMethod("Handle")); await(Task) fastInvoker(handler, new object[] { integrationEvent }); } catch { if (!_persistentConnection.IsConnected) { _persistentConnection.TryConnect(); } retryCount = GetRetryCount(properties); using (var channel = _persistentConnection.CreateModel()) { if (retryCount > _retryCount) { // 重试次数大于3次,则自动加入到死信队列 var rollbackCount = retryCount - _retryCount; if (rollbackCount < _rollbackCount) { IDictionary <String, Object> headers = new Dictionary <String, Object>(); if (!headers.ContainsKey("x-orig-routing-key")) { headers.Add("x-orig-routing-key", GetOrigRoutingKey(properties, eventName)); } retryCount = rollbackCount; channel.BasicPublish(_exchanges[QueueConsumerMode.Fail], eventName, CreateOverrideProperties(properties, headers), body); } } else { IDictionary <String, Object> headers = properties.Headers; if (headers == null) { headers = new Dictionary <String, Object>(); } if (!headers.ContainsKey("x-orig-routing-key")) { headers.Add("x-orig-routing-key", GetOrigRoutingKey(properties, eventName)); } channel.BasicPublish(_exchanges[QueueConsumerMode.Retry], eventName, CreateOverrideProperties(properties, headers), body); } } } finally { var baseConcreteType = typeof(BaseIntegrationEventHandler <>).MakeGenericType(eventType); if (handler.GetType().BaseType == baseConcreteType) { var context = new EventContext() { Content = integrationEvent, Count = retryCount, Type = mode.ToString() }; var fastInvoker = GetHandler($"{baseConcreteType.FullName}.Handled", baseConcreteType.GetMethod("Handled")); await(Task) fastInvoker(handler, new object[] { context }); } } } } }
private async Task ProcessEvent(string eventName, ReadOnlyMemory <byte> body, QueueConsumerMode type, IBasicProperties properties, bool bindConsumer) { var message = Encoding.UTF8.GetString(body.ToArray()); var eventType = _subscriptionsManager.GetEventTypeByName(eventName); var integrationEvent = JsonConvert.DeserializeObject(message, eventType); var handlers = _subscriptionsManager.GetHandlersForEvent(eventName); var concreteType = typeof(IEventHandler <>).MakeGenericType(eventType); foreach (var item in handlers) { var handler = item.DynamicInvoke(); long count = 1; try { if (type == QueueConsumerMode.Normal || type == QueueConsumerMode.Retry) { var fastInvoker = GetHandler($"{concreteType.FullName}.Handle", concreteType.GetMethod("Handle")); await(Task) fastInvoker(handler, new object[] { integrationEvent }); } } catch { if (!_rabbitMqClient.IsConnected) { _rabbitMqClient.TryConnect(); } count = GetRetryCount(properties); using (var channel = _rabbitMqClient.CreateModel()) { if (count > _retryCount) { // 重试次数大于设置次数,则自动加入到死信队列 var rollbackCount = count - _retryCount; if (rollbackCount <= _rollbackCount) { IDictionary <String, Object> headers = new Dictionary <String, Object>(); if (!bindConsumer) { return; } if (!headers.ContainsKey("x-orig-routing-key")) { headers.Add("x-orig-routing-key", GetOrigRoutingKey(properties, eventName)); } channel.BasicPublish($"{BROKER_NAME}@{QueueConsumerMode.Fail.ToString()}", eventName, CreateOverrideProperties(properties, headers), body); } } else { if (!bindConsumer) { return; } IDictionary <String, Object> headers = properties.Headers ?? new Dictionary <String, Object>(); if (!headers.ContainsKey("x-orig-routing-key")) { headers.Add("x-orig-routing-key", GetOrigRoutingKey(properties, eventName)); } channel.BasicPublish($"{BROKER_NAME}@{QueueConsumerMode.Retry.ToString()}", eventName, CreateOverrideProperties(properties, headers), body); } } } finally { var baseConcreteType = typeof(BaseEventHandler <>).MakeGenericType(eventType); if (handler.GetType().BaseType == baseConcreteType) { var context = new EventContext() { Content = integrationEvent, Count = count, Type = type.ToString() }; switch (type) { case QueueConsumerMode.Normal: case QueueConsumerMode.Retry: { var fastInvoker = GetHandler($"{baseConcreteType.FullName}.Handled", baseConcreteType.GetMethod("Handled")); await(Task) fastInvoker(handler, new object[] { context }); break; } case QueueConsumerMode.Fail: { var fastInvoker = GetHandler($"{baseConcreteType.FullName}.FailHandler", baseConcreteType.GetMethod("FailHandler")); await(Task) fastInvoker(handler, new object[] { context }); break; } } } } } }