RAbbitMQ:如何使用EventBasicConsumer

时间:2018-04-09 08:43:47

标签: c# .net rabbitmq

我们有一些队列,错误队列数相同。

我的老板让我写一个Window Service来使用错误队列,并将数据传输到DB。 Windows服务应该能够根据在DB表中设置的配置来管理应该使用哪些队列,这意味着,例如,如果我不想再使用特定队列, 我必须能够在DB上禁用该特定队列的配置,而不必停止Window Service。

我计划在Quartz的帮助下编写Windows服务作业,每个日程安排的Job应该读取数据库配置,打开单个连接, 为所有队列启动任务,使用每个任务一个通道消耗队列。有了这个解决方案,我希望能解决,因为在任务结束时渠道将被关闭, 连接将被关闭,错误队列将被消耗,并且在下一个作业计划中,要读取的队列的数量和名称可能不同。 此外,在每个计划中消耗每个队列的所有消息shuld保存打开/关闭连接/通道,如果我按每个计划消耗单个消息,则可能是繁重的, 所以计划的时间应该足以在下一个计划之前消耗队列中的所有错误消息。 此外,调度队列将使我有机会配置队列在DB中使用,而无需停止Windows服务。

现在我写了一些代码来测试使用单队列的解决方案

var consumer = new QueueingBasicConsumer(channel);
channel.BasicConsume(queueParName, autoAck: false, consumer: consumer);
bool queueEmpty = false;
while (!queueEmpty)
{
    try
        BasicDeliverEventArgs result;
        bool bRead = consumer.Queue.Dequeue(timeOutQueueEmpty, out result);

        if (bRead)
        {
            var msgBody = Encoding.UTF8.GetString(result.Body);
            // TO DB ...
        }
        else
        {
            queueEmpty = true;
        }
    }
    catch (EndOfStreamException ex)
    {
        // ...
    }
}

问题是 QueueingBasicConsumer 已经过时,并且在很多地方写的是prefear EventBasicConsumer

var consumer = new EventingBasicConsumer(channel);
consumer.Received += (model, ea) =>
{
    var body = ea.Body;
    var message = Encoding.UTF8.GetString(body);

    // TO DB...
};
channel.BasicConsume(queue: queueParName, autoAck: true, consumer: consumer);

但是使用EventBasicConsumer我无法理解当队列为空时如何停止消耗以便连接和通道

修改

评论中提到的一些更深层次的解释。 将所有代码放在这里是很困难的,因为我们使用了很多公司的编译库,因此代码不是完全可以理解的。 无论如何,简化:

  1. 我有一个Host项目,其中使用Quartz Package每N次安排一个Job。
  2. ...

    var schedule = SimpleScheduleBuilder.Create();
    schedule.WithIntervalInSeconds(ConfigurationManager.AppSettings["..."]);
    schedule.RepeatForever();
    s.ScheduleQuartzJob(q =>
        q.WithJob(() =>
            JobBuilder.Create<RabbitErrorDequeuerJob>().Build())
                .AddTrigger(() =>
                    TriggerBuilder.Create()
                        .WithSchedule(schedule)
                        .Build())
    );
    

    ...

    有Ninject IOC,在模块文件中我注入了连接

    // *** Ninject disposes every Disposable object that has another scope other than InTransientScope
    Bind<IConnection>().ToMethod(x =>
    {
    IConnectionFactory cnf = new ConnectionFactory();
    cnf.Uri = new Uri(ConfigurationManager.AppSettings["..."]);
    return cnf.CreateConnection();
    }).InCallScope();
    

    我有一个Job项目,每隔N次由Quartz安排,我有Execute方法(Quartz.IJob接口)

     public void Execute(IJobExecutionContext context)
        {
            try
            {
                List<RabbitQueueConfiguration> lst = //...LIST OF QUEUTE TO DEQUE FROM DATABASE
                foreach (RabbitQueueConfiguration queue in lst)
                {
                    Task t = Task.Factory.StartNew(() =>
                    {
                        DequeuSingleQueue(queue);
                    });
                }
            }
            catch (Exception ex)
            {
                _log.FatalFormat("Error ", ex.Message);
                throw;
            }
        }
    

    在DequeuSingleQueue(队列)中有出列的核心

1 个答案:

答案 0 :(得分:0)

RabbitMQ团队监控the rabbitmq-users mailing list,有时只回答StackOverflow上的问题。

您应该使用BasicGet一次一个地处理邮件。