RabbitMQ的确认机制

RabbitMQ的确认机制

生产者确认

csharp 复制代码
public class ProductionMessageConfirm
{
    public static void Send()
    {
        ConnectionFactory factory = new ConnectionFactory();
        factory.HostName = "localhost";//RabbitMQ服务在本地运行
        factory.UserName = "guest";//用户名
        factory.Password = "guest";//密码 
        using (var connection = factory.CreateConnection())
        {
            //创建通道channel
            using (var channel = connection.CreateModel())
            {
                Console.WriteLine("生产者准备就绪....");
                channel.QueueDeclare(queue: "ConfirmSelectQueue", durable: true, exclusive: false, 
                                     autoDelete: false, arguments: null);
                //声明交换机exchang
                channel.ExchangeDeclare(exchange: "ConfirmSelectQueueExchange", type: ExchangeType.Direct, durable: true,
                                        autoDelete: false, arguments: null);
                //绑定exchange和queue
                channel.QueueBind(queue: "ConfirmSelectQueue", exchange: "ConfirmSelectQueueExchange", 
                                  routingKey: "ConfirmSelectKey");
                string message = "";

                //发送消息
                //在控制台输入消息,按enter键发送消息
                while (!message.Equals("quit", StringComparison.CurrentCultureIgnoreCase))
                {
                    message = Console.ReadLine();
                    var body = Encoding.UTF8.GetBytes(message);
                    try
                    {
                        //开启消息确认模式
                        channel.ConfirmSelect();//基于当前这个channel 开启消息确认机制 
                        //发送消息
                        channel.BasicPublish(exchange: "ConfirmSelectQueueExchange", routingKey: "ConfirmSelectKey", 
                                             basicProperties: null, body: body);
                        //事务提交 

                        //调用WaitForConfirms 方法来判断如果消息正常发送,就返回true,否则就返回false
                        if (channel.WaitForConfirms()) //如果一条消息或多消息都确认发送
                        {
                            Console.WriteLine($"【{message}】发送到Broke成功!");
                        }
                        else
                        {
                            //可以记录个日志,重试一下;
                        }

                        //通过当前信道,调用WaitForConfirmsOrDie,如果所有消息发送成功 就正常执行;如果有消息发送失败;就抛出异常;
                        //channel.WaitForConfirmsOrDie();//如果所有消息发送成功 就正常执行;如果有消息发送失败;就抛出异常;
                    }
                    catch (Exception)
                    {
                        Console.WriteLine($"【{message}】发送到Broker失败!");
                        //就应该通知管理员
                        // 重新试一下
                    }
                }
                Console.Read();
            }
        }
    }
}

生产者事务版确认

csharp 复制代码
public class ProductionMessageTx
{
    public static void Send()
    {
        ConnectionFactory factory = new ConnectionFactory();
        factory.HostName = "localhost";//RabbitMQ服务在本地运行
        factory.UserName = "guest";//用户名
        factory.Password = "guest";//密码 
        using (var connection = factory.CreateConnection())
        {
            //创建通道channel
            using (var channel = connection.CreateModel())
            {
                Console.WriteLine("生产者准备就绪....");
                channel.QueueDeclare(queue: "MessageTxQueue01", durable: true, exclusive: false, 
                                     autoDelete: false, arguments: null);
                channel.QueueDeclare(queue: "MessageTxQueue02", durable: true, exclusive: false, 
                                     autoDelete: false, arguments: null);
                //声明交换机exchang
                channel.ExchangeDeclare(exchange: "MessageTxQueueExchange", type: ExchangeType.Direct, durable: true, 
                                        autoDelete: false, arguments: null);
                //绑定exchange和queue
                channel.QueueBind(queue: "MessageTxQueue01", exchange: "MessageTxQueueExchange", 
                                  routingKey: "MessageTxKey01");
                channel.QueueBind(queue: "MessageTxQueue02", exchange: "MessageTxQueueExchange", 
                                  routingKey: "MessageTxKey02");
                string message = "";
                //发送消息
                //在控制台输入消息,按enter键发送消息
                while (!message.Equals("quit", StringComparison.CurrentCultureIgnoreCase))
                {
                    message = Console.ReadLine();
                    var body = Encoding.UTF8.GetBytes(message);
                    try
                    {
                        //通过当前信道调用TxSelect方法开启事务机制---RabbitMQ  AMQP协议,强事务保证;
                        channel.TxSelect(); //事务是协议支持的
                        //发送消息
                        //同时给多个队列发送消息;要么都成功;要么都失败;

                        //执行下面这两句话,都不会吧消息发送到队列中去;
                        channel.BasicPublish(exchange: "MessageTxQueueExchange", routingKey: "MessageTxKey01", 
                                             basicProperties: null, body: body);
                        channel.BasicPublish(exchange: "MessageTxQueueExchange", routingKey: "MessageTxKey02", 
                                             basicProperties: null, body: body);
                        //事务提交
                        channel.TxCommit(); //只有事务提交成功以后,才会真正的写入到队列里面去
                        //如果失败---抛出异常;
                        Console.WriteLine($"【{message}】发送到Broke成功!");
                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine($"【{message}】发送到Broker失败!");
                        channel.TxRollback(); //事务回滚   或者重试一下;
                        throw;
                    }
                }
                Console.Read();
            }
        }
    }
}

消费者确认

自动确认

csharp 复制代码
public class ConsumerMessageConfirm
{
    public static void Consumption()
    {
        var factory = new ConnectionFactory();
        factory.HostName = "localhost";//RabbitMQ服务在本地运行
        factory.UserName = "guest";//用户名
        factory.Password = "guest";//密码 
        using (var connection = factory.CreateConnection())
        {
            using (IModel channel = connection.CreateModel())
            {
                #region EventingBasicConsumer
                //定义消费者                                      
                var consumer = new EventingBasicConsumer(channel);
                int i = 1;
                consumer.Received += (model, ea) =>
                {
                    if (i == 11)
                    {
                        throw new Exception("");
                    }
                    i++;
                    Console.WriteLine(Encoding.UTF8.GetString(ea.Body.ToArray()));
                };
                Console.WriteLine("消费者准备就绪....");
                //处理消息 
                //autoAck: true 自动确认:消息队列的消息直接推送给当前这个消费者;
                //照单全收,消费是否正常消费,RabbitMQ不管;
                channel.BasicConsume(queue: "PersistenceQueue", autoAck: true, consumer: consumer);
                Console.ReadKey();
                #endregion
            }
        }
    }
}

消费后确认

csharp 复制代码
public class ConsumptionACKConfirm
{
    public static void Consumption()
    {
        var factory = new ConnectionFactory();
        factory.HostName = "localhost";//RabbitMQ服务在本地运行
        factory.UserName = "guest";//用户名
        factory.Password = "guest";//密码 
        using (var connection = factory.CreateConnection())
        {
            using (IModel channel = connection.CreateModel())
            {
                #region EventingBasicConsumer
                //定义消费者                                      
                var consumer = new EventingBasicConsumer(channel);
                int i = 0;
                consumer.Received += (model, ea) =>
                {
                    var message = Encoding.UTF8.GetString(ea.Body.ToArray());
                    //如果在这里处理消息的手,异常了呢? 
                    //Console.WriteLine($"接收到消息:{message}"); ; 
                    if (i < 50)
                    {
                        //手动确认  消息正常消费  告诉Broker:你可以把当前这条消息删除掉了
                        channel.BasicAck(deliveryTag: ea.DeliveryTag, multiple: false);
                        Console.WriteLine(message);
                    }
                    else
                    {
                        //否定:告诉Broker,这个消息我没有正常消费;  requeue: true:重新写入到队列里去; false:你还是删除掉;
                        channel.BasicReject(deliveryTag: ea.DeliveryTag, requeue: true);
                    }
                    i++;
                };
                Console.WriteLine("消费者准备就绪....");
                {
                    //处理消息 
                    //autoAck: true 自动确认; 
                    //channel.BasicConsume(queue: "ConsumptionACKConfirmQueue", autoAck: true, consumer: consumer);
                }
                {
                    //处理消息 
                    //autoAck: false  显示确认; 
                    channel.BasicConsume(queue: "PersistenceQueue", autoAck: false, consumer: consumer);
                }
                 
                Console.ReadKey();
                #endregion
            }
        }
    }
}
相关推荐
꧁薄暮꧂15 分钟前
kafka是如何处理数据乱序问题
分布式·kafka
CodingBrother1 小时前
RabbitMQ高效的消息队列中间件原理及实践
中间件·rabbitmq
songqq271 小时前
【快速解决】kafka崩了,重启之后,想继续消费,怎么做?
分布式·kafka
zmd-zk1 小时前
hive中windows子句的使用
大数据·数据仓库·hive·hadoop·windows·分布式·big data
不脱发的牧码人3 小时前
C#中Task和Thread的全解析
c#·多线程·thread·task
CodingBrother4 小时前
RabbitMQ 与 PHP Swoole 实现
rabbitmq·php·swoole
斑驳竹影9 小时前
【RabbitMQ】之高可用集群搭建
分布式·rabbitmq
IT规划师9 小时前
开源 - Ideal库 - 常用枚举扩展方法(一)
开源·c#·.net core·ideal库·枚举转换
P.H. Infinity9 小时前
【RabbitMQ】07-业务幂等处理
java·rabbitmq·java-rabbitmq
floret*10 小时前
Kafka高频面试题详解
分布式·kafka