RabbitMQ在c#客户端上手动确认

时间:2016-05-18 18:25:23

标签: c# rabbitmq

我正在尝试在非常简单的控制台应用程序上使用手动ACK,但我无法使其正常工作。

在发件人身上,我有以下代码:

var factory = new ConnectionFactory() { HostName = "localhost" };
using (var connection = factory.CreateConnection())
using (var channel = connection.CreateModel())
{
    channel.QueueDeclare(queue: "task_queue",
                         durable: true,
                         exclusive: false,
                         autoDelete: false,
                         arguments: null);

    var message = GetMessage(args);
    var body = Encoding.UTF8.GetBytes(message);

    channel.ConfirmSelect();
    channel.BasicAcks += (sender, e) =>
    {
        Console.Write("ACK received");
    };

    var properties = channel.CreateBasicProperties();

    channel.BasicPublish(exchange: "",
                         routingKey: "task_queue",
                         basicProperties: properties,
                         body: body);

    Console.WriteLine(" [x] Sent {0}", message);
}

Console.WriteLine(" Press [enter] to exit.");
Console.ReadLine();

在接收器上我有以下代码:

var factory = new ConnectionFactory() { HostName = "localhost" };
using (var connection = factory.CreateConnection())
using (var channel = connection.CreateModel())
{
    channel.QueueDeclare(queue: "task_queue",
                         durable: true,
                         exclusive: false,
                         autoDelete: false,
                         arguments: null);

    channel.BasicQos(prefetchSize: 0, prefetchCount: 1, global: false);
    channel.ConfirmSelect();

    Console.WriteLine(" [*] Waiting for messages.");

    var consumer = new EventingBasicConsumer(channel);
    consumer.Received += (model, ea) =>
    {
        var body = ea.Body;
        var message = Encoding.UTF8.GetString(body);
        Console.WriteLine(" [x] Received {0}", message);

        int dots = message.Split('.').Length - 1;
        Thread.Sleep(dots * 1000);

        channel.BasicAck(deliveryTag: ea.DeliveryTag, multiple: false);
        Console.WriteLine(" [x] Done");
    };
    channel.BasicConsume(queue: "task_queue",
                         noAck: false,
                         consumer: consumer);

    Console.WriteLine(" Press [enter] to exit.");
    Console.ReadLine();
}

我期望在我在接收方上调用BasicAcks时触发发件人的事件channel.BasicAck(),但是在将消息传递给客户端之前,该事件被触发consumer.Received 1}}。

我期待的是正确的行为还是我错过了什么?

2 个答案:

答案 0 :(得分:6)

您的期望不正确。 BasicAcks约为publisher confirms,与接收者无关。因此,您将消息发布到代理和代理(因此,RabbitMQ本身)将在处理此消息时确认或拒绝(否定确认)(例如,当它将其写入磁盘以获取持久消息时) ,或在将其放入队列时)。请注意,此处不涉及接收者 - 它完全在发布者和RabbitMQ之间。

现在,当你在接收器上发出消息时 - 仅在接收器和RabbitMQ之间再次发送消息 - 你告诉兔子消息已被处理并可以安全地删除。这样做是为了处理接收器在处理期间崩溃的情况 - 然后兔子将能够将此消息传递给下一个接收器(如果有的话)。

请注意,此类结构的整个目的是将发布者和接收者分开 - 它们不应相互依赖。

如果您有一个接收器(可能有很多)并且您想确保它处理您的消息 - 请使用RPC模式:发送消息并等待来自此接收器的另一条消息。

答案 1 :(得分:-1)

消费者:

:scriptnames