posts - 16,  comments - 4,  views - 4045
< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

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

  自动确认,消费者消费消息时,只要收到消息就回馈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   Fletcher  阅读(1260)  评论(0编辑  收藏  举报
编辑推荐:
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
点击右上角即可分享
微信分享提示