Beispiel #1
0
        private void HandleMessage(ConsumingMessage consumingMessage)
        {
            if (_stoped)
            {
                return;
            }
            if (consumingMessage == null)
            {
                return;
            }
            if (consumingMessage.ProcessQueue.IsDropped)
            {
                return;
            }

            try
            {
                _messageHandler.Handle(consumingMessage.Message, new MessageContext(currentQueueMessage => RemoveHandledMessage(consumingMessage)));
            }
            catch (Exception ex)
            {
                //TODO,目前,对于消费失败(遇到异常)的消息,我们先记录错误日志,然后将该消息放入本地内存的重试队列;
                //放入重试队列后,会定期对该消息进行重试,重试队列中的消息会每隔1s被取出一个来重试。
                //通过这样的设计,可以确保消费有异常的消息不会被认为消费已成功,也就是说不会从ProcessQueue中移除;
                //但不影响该消息的后续消息的消费,该消息的后续消息仍然能够被消费,但是ProcessQueue的消费位置,即滑动门不会向前移动了;
                //因为只要该消息一直消费遇到异常,那就意味着该消息所对应的queueOffset不能被认为已消费;
                //而我们发送到broker的是当前最小的已被成功消费的queueOffset,所以broker上记录的当前queue的消费位置(消费进度)不会往前移动,
                //直到当前失败的消息消费成功为止。所以,如果我们重启了消费者服务器,那下一次开始消费的消费位置还是从当前失败的位置开始,
                //即便当前失败的消息的后续消息之前已经被消费过了;所以应用需要对每个消息的消费都要支持幂等,不过enode对所有的command和event的处理都支持幂等;
                //以后,我们会在broker上支持重试队列,然后我们可以将消费失败的消息发回到broker上的重试队列,发回到broker上的重试队列成功后,
                //就可以让当前queue的消费位置往前移动了。
                LogMessageHandlingException(consumingMessage, ex);
                _messageRetryQueue.Add(consumingMessage);
            }
        }
Beispiel #2
0
        private void RemoveHandledMessage(ConsumingMessage consumingMessage)
        {
            ConsumingMessage consumedMessage;

            if (_handlingMessageDict.TryRemove(consumingMessage.Message.MessageOffset, out consumedMessage))
            {
                consumedMessage.ProcessQueue.RemoveMessage(consumedMessage.Message);
            }
        }
Beispiel #3
0
        private void RemoveHandledMessage(ConsumingMessage consumingMessage)
        {
            ConsumingMessage consumedMessage;

            if (_handlingMessageDict.TryRemove(consumingMessage.Message.RoutingKey, out consumedMessage))
            {
                _finishedMessageTag.Enqueue(consumingMessage.Message.DeliveryTag);
            }
        }
Beispiel #4
0
 private void LogMessageHandlingException(ConsumingMessage consumingMessage, Exception exception)
 {
     _logger.Error(string.Format(
                       "Message handling has exception, message info:[topic={0}, queueId={1}, queueOffset={2}, storedTime={3}, group={4}]",
                       consumingMessage.Message.Topic,
                       consumingMessage.Message.QueueId,
                       consumingMessage.Message.QueueOffset,
                       consumingMessage.Message.StoredTime,
                       GroupName), exception);
 }
Beispiel #5
0
 private void LogMessageHandlingException(ConsumingMessage consumingMessage, Exception exception)
 {
     _logger.Error(string.Format(
                       "Message handling has exception, message info:[messageId:{0}, topic:{1}, queueId:{2}, queueOffset:{3}, createdTime:{4}, storedTime:{5}, consumerGroup:{6}]",
                       consumingMessage.Message.MessageId,
                       consumingMessage.Message.Topic,
                       consumingMessage.Message.QueueId,
                       consumingMessage.Message.QueueOffset,
                       consumingMessage.Message.CreatedTime,
                       consumingMessage.Message.StoredTime,
                       GroupName), exception);
 }
Beispiel #6
0
 public void RemoveMessage(ConsumingMessage consumingMessage)
 {
     lock (_lockObj)
     {
         if (_messageDict.Remove(consumingMessage.Message.QueueOffset))
         {
             if (_messageDict.Keys.IsNotEmpty())
             {
                 _consumedQueueOffset = _messageDict.Keys.First() - 1;
             }
             else
             {
                 _consumedQueueOffset = _maxQueueOffset;
             }
             _messageCount--;
         }
     }
 }
Beispiel #7
0
 public void RemoveMessage(ConsumingMessage consumingMessage)
 {
     lock (_lockObj)
     {
         if (_messageDict.Remove(consumingMessage.Message.QueueOffset))
         {
             if (_messageDict.Keys.IsNotEmpty())
             {
                 _consumedQueueOffset = _messageDict.Keys.First() - 1;
             }
             else
             {
                 _consumedQueueOffset = _maxQueueOffset;
             }
             _messageCount--;
         }
     }
 }
Beispiel #8
0
 private void RemoveHandledMessage(ConsumingMessage consumedMessage)
 {
     consumedMessage.ProcessQueue.RemoveMessage(consumedMessage.Message);
 }
Beispiel #9
0
        private void ProcessPullResponse(PullRequest pullRequest, RemotingResponse remotingResponse)
        {
            if (remotingResponse == null)
            {
                _logger.ErrorFormat("Pull message response is null, pullRequest:{0}", pullRequest);
                SchedulePullRequest(pullRequest);
                return;
            }

            if (remotingResponse.Code == -1)
            {
                _logger.ErrorFormat("Pull message failed, pullRequest:{0}, errorMsg:{1}", pullRequest, Encoding.UTF8.GetString(remotingResponse.Body));
                SchedulePullRequest(pullRequest);
                return;
            }

            if (remotingResponse.Code == (short)PullStatus.Found)
            {
                var messages = DecodeMessages(pullRequest, remotingResponse.Body);
                if (messages.Count() > 0)
                {
                    var filterMessages = messages.Where(x => IsQueueMessageMatchTag(x, pullRequest.Tags));
                    pullRequest.ProcessQueue.AddMessages(filterMessages);
                    foreach (var message in filterMessages)
                    {
                        var consumingMessage = new ConsumingMessage(message, pullRequest.ProcessQueue);
                        if (Setting.MessageHandleMode == MessageHandleMode.Sequential)
                        {
                            _consumingMessageQueue.Add(consumingMessage);
                        }
                        else
                        {
                            Task.Factory.StartNew(HandleMessage, consumingMessage);
                        }
                    }
                    pullRequest.NextConsumeOffset = messages.Last().QueueOffset + 1;
                }
            }
            else if (remotingResponse.Code == (short)PullStatus.NextOffsetReset)
            {
                var newOffset = BitConverter.ToInt64(remotingResponse.Body, 0);
                var oldOffset = pullRequest.NextConsumeOffset;
                pullRequest.NextConsumeOffset = newOffset;
                _logger.InfoFormat("Reset queue next consume offset. topic:{0}, queueId:{1}, old offset:{2}, new offset:{3}", pullRequest.MessageQueue.Topic, pullRequest.MessageQueue.QueueId, oldOffset, newOffset);
            }
            else if (remotingResponse.Code == (short)PullStatus.NoNewMessage)
            {
                if (_logger.IsDebugEnabled)
                {
                    _logger.DebugFormat("No new message found, pullRequest:{0}", pullRequest);
                }
            }
            else if (remotingResponse.Code == (short)PullStatus.Ignored)
            {
                if (_logger.IsDebugEnabled)
                {
                    _logger.DebugFormat("Pull request was ignored, pullRequest:{0}", pullRequest);
                }
                return;
            }
            else if (remotingResponse.Code == (short)PullStatus.BrokerIsCleaning)
            {
                Thread.Sleep(5000);
            }

            //Schedule the next pull request.
            SchedulePullRequest(pullRequest);
        }
Beispiel #10
0
 private void LogMessageHandlingException(ConsumingMessage consumingMessage, Exception exception)
 {
     _logger.Error(string.Format(
         "Message handling has exception, message info:[messageId:{0}, topic:{1}, queueId:{2}, queueOffset:{3}, createdTime:{4}, storedTime:{5}, consumerGroup:{6}]",
         consumingMessage.Message.MessageId,
         consumingMessage.Message.Topic,
         consumingMessage.Message.QueueId,
         consumingMessage.Message.QueueOffset,
         consumingMessage.Message.CreatedTime,
         consumingMessage.Message.StoredTime,
         GroupName), exception);
 }
Beispiel #11
0
 private void RemoveHandledMessage(ConsumingMessage consumedMessage)
 {
     consumedMessage.ProcessQueue.RemoveMessage(consumedMessage.Message);
 }
Beispiel #12
0
        private void ProcessPullResponse(PullRequest pullRequest, RemotingResponse remotingResponse)
        {
            if (remotingResponse == null)
            {
                _logger.ErrorFormat("Pull message response is null, pullRequest:{0}", pullRequest);
                SchedulePullRequest(pullRequest);
                return;
            }

            if (remotingResponse.Code == -1)
            {
                _logger.ErrorFormat("Pull message failed, pullRequest:{0}, errorMsg:{1}", pullRequest, Encoding.UTF8.GetString(remotingResponse.Body));
                SchedulePullRequest(pullRequest);
                return;
            }

            if (remotingResponse.Code == (short)PullStatus.Found)
            {
                var messages = DecodeMessages(pullRequest, remotingResponse.Body);
                if (messages.Count() > 0)
                {
                    var filterMessages = messages.Where(x => IsQueueMessageMatchTag(x, pullRequest.Tags));
                    pullRequest.ProcessQueue.AddMessages(filterMessages);
                    foreach (var message in filterMessages)
                    {
                        var consumingMessage = new ConsumingMessage(message, pullRequest.ProcessQueue);
                        if (Setting.MessageHandleMode == MessageHandleMode.Sequential)
                        {
                            _consumingMessageQueue.Add(consumingMessage);
                        }
                        else
                        {
                            Task.Factory.StartNew(HandleMessage, consumingMessage);
                        }
                    }
                    pullRequest.NextConsumeOffset = messages.Last().QueueOffset + 1;
                }
            }
            else if (remotingResponse.Code == (short)PullStatus.NextOffsetReset)
            {
                var newOffset = BitConverter.ToInt64(remotingResponse.Body, 0);
                var oldOffset = pullRequest.NextConsumeOffset;
                pullRequest.NextConsumeOffset = newOffset;
                pullRequest.ProcessQueue.Reset();
                _logger.InfoFormat("Reset queue next consume offset. topic:{0}, queueId:{1}, old offset:{2}, new offset:{3}", pullRequest.MessageQueue.Topic, pullRequest.MessageQueue.QueueId, oldOffset, newOffset);
            }
            else if (remotingResponse.Code == (short)PullStatus.NoNewMessage)
            {
                if (_logger.IsDebugEnabled)
                {
                    _logger.DebugFormat("No new message found, pullRequest:{0}", pullRequest);
                }
            }
            else if (remotingResponse.Code == (short)PullStatus.Ignored)
            {
                if (_logger.IsDebugEnabled)
                {
                    _logger.DebugFormat("Pull request was ignored, pullRequest:{0}", pullRequest);
                }
                return;
            }
            else if (remotingResponse.Code == (short)PullStatus.BrokerIsCleaning)
            {
                Thread.Sleep(5000);
            }

            //Schedule the next pull request.
            SchedulePullRequest(pullRequest);
        }
Beispiel #13
0
 private void RemoveHandledMessage(ConsumingMessage consumingMessage)
 {
     ConsumingMessage consumedMessage;
     if (_handlingMessageDict.TryRemove(consumingMessage.Message.MessageOffset, out consumedMessage))
     {
         consumedMessage.ProcessQueue.RemoveMessage(consumedMessage.Message);
     }
 }
Beispiel #14
0
 private void LogMessageHandlingException(ConsumingMessage consumingMessage, Exception exception)
 {
     _logger.Error(string.Format(
         "Message handling has exception, message info:[messageOffset={0}, topic={1}, queueId={2}, queueOffset={3}, storedTime={4}, consumerId={5}, group={6}]",
         consumingMessage.Message.MessageOffset,
         consumingMessage.Message.Topic,
         consumingMessage.Message.QueueId,
         consumingMessage.Message.QueueOffset,
         consumingMessage.Message.StoredTime,
         Id,
         GroupName), exception);
 }
Beispiel #15
0
        private void HandleMessage(ConsumingMessage consumingMessage)
        {
            if (_stoped) return;
            if (consumingMessage == null) return;
            if (consumingMessage.ProcessQueue.IsDropped) return;

            try
            {
                _messageHandler.Handle(consumingMessage.Message, new MessageContext(currentQueueMessage => RemoveHandledMessage(consumingMessage)));
            }
            catch (Exception ex)
            {
                //TODO,目前,对于消费失败(遇到异常)的消息,我们先记录错误日志,然后将该消息放入本地内存的重试队列;
                //放入重试队列后,会定期对该消息进行重试,重试队列中的消息会每隔1s被取出一个来重试。
                //通过这样的设计,可以确保消费有异常的消息不会被认为消费已成功,也就是说不会从ProcessQueue中移除;
                //但不影响该消息的后续消息的消费,该消息的后续消息仍然能够被消费,但是ProcessQueue的消费位置,即滑动门不会向前移动了;
                //因为只要该消息一直消费遇到异常,那就意味着该消息所对应的queueOffset不能被认为已消费;
                //而我们发送到broker的是当前最小的已被成功消费的queueOffset,所以broker上记录的当前queue的消费位置(消费进度)不会往前移动,
                //直到当前失败的消息消费成功为止。所以,如果我们重启了消费者服务器,那下一次开始消费的消费位置还是从当前失败的位置开始,
                //即便当前失败的消息的后续消息之前已经被消费过了;所以应用需要对每个消息的消费都要支持幂等,不过enode对所有的command和event的处理都支持幂等;
                //以后,我们会在broker上支持重试队列,然后我们可以将消费失败的消息发回到broker上的重试队列,发回到broker上的重试队列成功后,
                //就可以让当前queue的消费位置往前移动了。
                LogMessageHandlingException(consumingMessage, ex);
                _messageRetryQueue.Add(consumingMessage);
            }
        }