RabbitMQ一次又一次地返回相同的消息

时间:2015-04-25 19:43:04

标签: c# rabbitmq message-queue

我尝试对一个相当基本的场景进行单元测试 - 具有2个工作者和1个发布者场景的工作队列,但它不断地从队列中一遍又一遍地返回相同的消息。

测试中的以下代码只会将1到100条消息放入队列,而2位消费者会将它们消耗掉。问题是他们只是收到消息1和2.我试图将确认分成一个方法,因为在我的应用程序中,消息需要时间来获取进程(评论方法确认) - 然后它抛出了令牌未知的异常:

  

AMQP操作被中断:AMQP关闭原因,由...发起   同行,代码= 406,文本=" PRECONDITION_FAILED - 未知交货标签1",   classId = 60,methodId = 80,cause =

似乎承认在某种程度上被打破了。我试图把它关掉 - 没有运气。

using System;
using System.Text;
using Newtonsoft.Json;
using RabbitMQ.Client;
using RabbitMQ.Client.Events;

namespace Backend.MQ.OCR
{
    public class BatchQueue : QueueBase<BatchMessage>
    {
        private readonly IModel _channel;
        private const string QPrefix = "ocrbatches_";
        private readonly QueueingBasicConsumer _consumer;
        private ulong _latesttoken = ulong.MaxValue;
        private readonly string _jobid;
        public BatchQueue(string connectionString, String jobid):
            base(connectionString)
        {
            _jobid = jobid;
            var factory = new ConnectionFactory()
            {
                HostName = connectionString
            };
            var connection = factory.CreateConnection();
            _channel = connection.CreateModel();
            _channel.QueueDeclare(Name, true, false, false, null);
            //binding consumers
            _channel.BasicQos(0, 1, false);
            _consumer = new QueueingBasicConsumer(_channel);
            _channel.BasicConsume(Name, false, _consumer);
        }

        public override void Publish(BatchMessage msg)
        {
            var message = JsonConvert.SerializeObject(msg);
            var body = Encoding.UTF8.GetBytes(message);
            var properties = _channel.CreateBasicProperties();
            properties.SetPersistent(true);
            _channel.BasicPublish("", Name, properties, body);
#if DEBUG
            System.Diagnostics.Trace.WriteLine("[x] Sent task:" + msg);
#endif 
        }

        private string Name
        {
            get { return QPrefix + _jobid; }
        } 

        public override BatchMessage Receive()
        {
            var ea =
                    (BasicDeliverEventArgs)_consumer.Queue.Dequeue();

            var body = ea.Body;
            _channel.BasicAck(ea.DeliveryTag, false);
            return JsonConvert.DeserializeObject<BatchMessage>(Encoding.UTF8.GetString(body));
        }


        public override void Confirm()
        {
            //if (_latesttoken < ulong.MaxValue) _channel.BasicAck(_latesttoken, false);
        }
    }
}

单元测试:

#if NUNIT
using TestClass = NUnit.Framework.TestFixtureAttribute;
using TestMethod = NUnit.Framework.TestAttribute;
using TestCleanup = NUnit.Framework.TearDownAttribute;
using TestInitialize = NUnit.Framework.SetUpAttribute;
using ClassCleanup = NUnit.Framework.TestFixtureTearDownAttribute;
using ClassInitialize = NUnit.Framework.TestFixtureSetUpAttribute;
#else
#endif
using System.Threading.Tasks;
using System.Threading;
using System;
using System.Collections.Generic;
using Backend.MQ.OCR;
using Microsoft.VisualStudio.TestTools.UnitTesting;
#if NUNIT
using MAssert = NUnit.Framework.Assert;
#else
using MAssert = Microsoft.VisualStudio.TestTools.UnitTesting.Assert;
#endif

namespace MQ.Test
{
    [TestClass]
    public class BatchQueueTest
    {
        [TestMethod]
        public void Concurrencytest()
        {
            var batchname = Guid.NewGuid().ToString();
            var queue = new BatchQueue("localhost", batchname);
            var tasks = new List<Task>();
            var counter = 0;
            for (int i = 0; i < 100; i++)
            {
                queue.Publish(new BatchMessage()
                {
                    Files = new List<string>() { i.ToString() }
                });
            }
            for (int i = 0; i < 2; i++)
            {
                var task = Task.Factory.StartNew(() =>
                {
                    var q = new BatchQueue("localhost", batchname);
                    var res = q.Receive();
                    while (res != null)
                    {
                        System.Diagnostics.Trace.WriteLine(res.Files[0]);
                        q.Confirm();
                        Interlocked.Increment(ref counter);
                    }
                });
                tasks.Add(task);
            }
            var ok = Task.WaitAll(tasks.ToArray(), TimeSpan.FromSeconds(30));
            MAssert.IsTrue(ok, "Tasks didnt complete in time");
            MAssert.AreEqual(counter, 100, "Not all messages have been processed");

        }
    }
}

1 个答案:

答案 0 :(得分:2)

您的单元测试启动两项任务。在while循环之前,您会收到一条消息,但是您仍然在while循环中确认相同的消息:

var res = q.Receive();

尝试将<ul> <li value="{name:34}">Item Two</li> </ul> 放入循环