消费者消息确认分两种:自动确认、手动确认。

  自动确认,消费者消费消息时,只要收到消息就回馈rabbitmq服务,

    并且消费成功一条消息后,rabbitmq会认为所有消息全部成功消费,队列中移除所有消息,会导致消息的丢失;

  手动确认,消费一条消息,回馈rabbitmq服务,rabbitmq只移除队列中消费了的消息;

 

1. 生产者

using RabbitMQMsgProducer.MessageProducer;
using Microsoft.Extensions.Configuration;
using System;
using System.IO;
using RabbitMQMsgProducer.ExchangeDemo;
using RabbitMQMsgProducer.MessageConfirm;

namespace RabbitMQMsgProducer
{
    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                {
                    // 消费者 确认消息
                    ConsumerMsgConfirm.Send();
                }
                Console.ReadLine();
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
        }
    }
}
using RabbitMQ.Client;
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;

namespace RabbitMQMsgProducer.MessageConfirm
{
    public class ConsumerMsgConfirm
    {
        public static void Send()
        {
            var factory = new ConnectionFactory();
            factory.HostName = "localhost";//服务地址
            factory.UserName = "guest";//用户名
            factory.Password = "guest";//密码 
            string queueName = "ConsumerMsgConfirmQueue";
            string exchangeName = "ConsumerMsgConfirmExchange";
            string routingKeyName = "ConsumerMsgConfirmRoutingKey";
            using (var connection = factory.CreateConnection())
            {
                using (IModel channel = connection.CreateModel())
                {
                    // 声明队列
                    channel.QueueDeclare(queue: queueName, durable: true, exclusive: false, autoDelete: false, arguments: null);
                    // 声明交换机exchange
                    channel.ExchangeDeclare(exchange: exchangeName, type: ExchangeType.Direct, durable: true, autoDelete: false, arguments: null);
                    // 绑定exchange和queue
                    channel.QueueBind(queue: queueName, exchange: exchangeName, routingKey: routingKeyName);

                    for (int i = 1; i <= 100; i++)
                    {
                        string message = $"the message is : {i} .";
                        channel.BasicPublish(exchange: exchangeName, routingKey: routingKeyName, basicProperties: null, body: Encoding.UTF8.GetBytes(message));

                        Thread.Sleep(300);
                        Console.WriteLine($"the message is : {i} . is send .");
                    }
                    Console.Read();

                }
            }
        }
    }
}

 

2. 消费者

using RabbitMQMsgConsumer001.ExchangeDemo;
using RabbitMQMsgConsumer001.MessageConfirm;
using RabbitMQMsgConsumer001.MessageConsumer;
using System;
using System.Threading.Tasks;

namespace RabbitMQMsgConsumer001
{
    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                {
                    // 消费者 确认消息
                    ConsumerMsgConfirm.Receive();
                }
                Console.ReadLine();
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
        }
    }
}
using RabbitMQ.Client;
using RabbitMQ.Client.Events;
using System;
using System.Collections.Generic;
using System.Text;

namespace RabbitMQMsgConsumer001.MessageConfirm
{
    public class ConsumerMsgConfirm
    {
        public static void Receive()
        {
            var factory = new ConnectionFactory();
            factory.HostName = "localhost";//服务地址
            factory.UserName = "guest";//用户名
            factory.Password = "guest";//密码 
            string queueName = "ConsumerMsgConfirmQueue";
            string exchangeName = "ConsumerMsgConfirmExchange";
            string routingKeyName = "ConsumerMsgConfirmRoutingKey";
            using (var connection = factory.CreateConnection())
            {
                using (IModel channel = connection.CreateModel())
                {
                    Console.WriteLine("the consumer is ready !");
                    // 声明队列
                    channel.QueueDeclare(queue: queueName, durable: true, exclusive: false, autoDelete: false, arguments: null);
                    // 声明交换机exchange
                    channel.ExchangeDeclare(exchange: exchangeName, type: ExchangeType.Direct, durable: true, autoDelete: false, arguments: null);
                    // 绑定exchange和queue
                    channel.QueueBind(queue: queueName, exchange: exchangeName, routingKey: routingKeyName);

                    EventingBasicConsumer consumer = new EventingBasicConsumer(channel);
                    int i = 0;
                    consumer.Received += (model, ea) =>
                    {
                        var body = ea.Body;
                        var msg = Encoding.UTF8.GetString(body.ToArray());
                        #region 自动确认
                        // 调试运行 消费第一条消息时,rabbitmq中的队列已经显示全部消费了
                        // Console.WriteLine($"the consumer received : {msg} over.");
                        #endregion
                        #region 手动确认
                        if (i < 20)
                        {
                            // 手动确认 消息已消费,通知broker 可从队列中移除这条消息
                            channel.BasicAck(deliveryTag: ea.DeliveryTag, multiple: false);
                            Console.WriteLine($"the consumer received : {msg} over.");
                        }
                        else
                        {
                            // 模拟未消费此消息或消费失败,通知broker;
                            // requeue: true 重新写入队列; false 不重新写入,直接移除掉此消息
                            channel.BasicReject(deliveryTag: ea.DeliveryTag, requeue: true);
                        }
                        #endregion
                        i++;
                    };
                    {
                        // 1.消费者自动确认 autoAck:true
                        //channel.BasicConsume(queue: queueName, autoAck: true, consumer: consumer);
                    }
                    {
                        // 2.消费者手动确认 autoAck:false
                        channel.BasicConsume(queue: queueName, autoAck: false, consumer: consumer);
                    }

                    Console.Read();
                }
            }
        }
    }
}

 

3. 结果

 

 生产者,停止生产, 重新启动消费者,将继续消费20条消息:

 

posted on 2021-01-18 19:46  Fletcher  阅读(1156)  评论(0编辑  收藏  举报