Exemplo n.º 1
0
        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);
        }
Exemplo n.º 2
0
        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);
        }
Exemplo n.º 3
0
        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 });
                        }
                    }
                }
            }
        }
Exemplo n.º 4
0
        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;
                        }
                        }
                    }
                }
            }
        }