rabbitmq 问题

.Net RabbitMQ实战指南——进阶(二) - Stacking - 博客园 (cnblogs.com)

 RabbitMQ提供了Confirm的确认机制。Confirm机制用于确认消息是否已经发送给了交换机

 await Channel.ConfirmSelectAsync();

 BasicProperties properties = new BasicProperties()
 {
     DeliveryMode = DeliveryModes.Persistent,
 };
 await Channel.BasicPublishAsync(exchange: exchange, routingKey: routingKey, body: Encoding.UTF8.GetBytes(message),
     mandatory: true, basicProperties: properties);

 if (await Channel.WaitForConfirmsAsync())
 {
     _logger.LogInformation($"{message},消息消息成功发送到交换机");
 };

  

//mandatory:设置为true时,如果exchange根据自身类型和消息routeKey无法找到一个符合条件的queue,
//会调用basic.return方法将消息返还给生产者;设为false时,出现上述情形broker会直接将消息扔掉。

 

  public async ValueTask BasicPublishAsync(string message, string exchange, string routingKey, BasicProperties basicProperties, ReadOnlyMemory<byte> body = default, bool mandatory = false, CancellationToken cancellationToken = default)
  {

      if (!Channel.IsOpen) throw new Exception($"rabbitmq 连接为关闭状态{Channel.IsOpen}");

      await Channel.ConfirmSelectAsync();
      BasicProperties properties = new BasicProperties()
      {
          DeliveryMode = DeliveryModes.Persistent,
      };
      //mandatory:设置为true时,如果exchange根据自身类型和消息routeKey无法找到一个符合条件的queue,
      //会调用basic.return方法将消息返还给生产者;设为false时,出现上述情形broker会直接将消息扔掉。

      await Channel.BasicPublishAsync(exchange: exchange, routingKey: routingKey, body: Encoding.UTF8.GetBytes(message),
          mandatory: true, basicProperties: properties);

      if (await Channel.WaitForConfirmsAsync())
      {
          _logger.LogInformation($"{message},消息消息成功发送到交换机");
      };

      Channel.BasicReturn += (sender, e) =>
      {
          _logger.LogInformation($"{message},消息没有匹配到路由");
      };
  }

 

 Channel.BasicNacks Channel.BasicAcks
//RabbitMQ会发送一个确认(Basic.Ack)给生产者(包含消息的唯一ID),告知生产者消息已经正确到达目的地。
//如果消息和队列是可持久化的,确认消息会在消息写入磁盘之后发出
   public async ValueTask BasicPublishAsync(string message, string exchange, string routingKey, CancellationToken cancellationToken = default)
   {
       if (!Channel.IsOpen) throw new Exception($"rabbitmq 连接为关闭状态{Channel.IsOpen}");
       await Channel.ConfirmSelectAsync();

       BasicProperties properties = new BasicProperties()
       {
           DeliveryMode = DeliveryModes.Persistent,
       };
       await Channel.BasicPublishAsync(exchange: exchange, routingKey: routingKey, body: Encoding.UTF8.GetBytes(message),
           mandatory: true, basicProperties: properties);

       //在使用RabbitMQ的时候,我们还会考虑的一个问题就是消息的生产者将消息发送出去之后,
       //消息有没有正确地到达服务器?默认情况下发送消息的操作不会返回任何信息给生产者,
       //也就是默认情况下生产者是不能确认消息有没有正确地到达服务器。

       //RabbitMQ针对这个问题,提供了两种解决方式:
       //通过事务机制实现(与数据库中的事务概念并不相同);
       //通过发送方确认(publisher confirm)机制实现。

       //事务机制
       //事务机制相关的方法有:channel.TxSelect、channel.TxCommit和channel.TxRollback。
       //    channel.TxSelect将当前的信道设置成事务模式,channel.TxCommit用于提交事务,
       //    channel.TxRollback用于事务回滚。通过channel.TxSelect方法开启事务之后,发布消息给RabbitMQ了,如果事务提交成功,
       //    则消息一定到达了RabbitMQ,如果在事务提交之前由于RabbitMQ异常崩溃或者其他原因抛出异常,
       //    通过执行channel.TxRollback方法来实现事务回滚。

       //if (await Channel.WaitForConfirmsAsync())
       //{
       //    _logger.LogInformation($"{message},消息消息成功发送到交换机");
       //};

       Channel.BasicAcks += (sender, e) =>
       {
           //RabbitMQ会发送一个确认(Basic.Ack)给生产者(包含消息的唯一ID),告知生产者消息已经正确到达目的地。
           //如果消息和队列是可持久化的,确认消息会在消息写入磁盘之后发出
           _logger.LogInformation($"{message},消息已经正确到达Broker并且Broker已经收到 返回ACK");
       };
       Channel.BasicNacks += (sender, e) =>
       {
           _logger.LogInformation($"{message},消息没有正确到达Broker");
       };
       Channel.BasicReturn += (sender, e) =>
       {
           _logger.LogInformation($"{message},消息到达Broker后但是Broker没有匹配到路由");
       };
   }

  

优先级队列

//x-max-priority属性必须设置,否则消息优先级不生效

channel.QueueDeclare(queueName, durable: true, exclusive: false, autoDelete: false, arguments: new Dictionary<string, object> { { "x-max-priority", 10 } });

  

 var properties = channel.CreateBasicProperties();
 messagePriority = (byte)random.Next(1, 10);
 properties.Priority = messagePriority;//设置消息优先级,取值范围在1~9之间。
 var message = MessagePrefix + i.ToString()+"____"+messagePriority;
 var body = Encoding.UTF8.GetBytes(message);
 channel.BasicPublish(exchange: exchange, routingKey: ExchangeType.Fanout, basicProperties: properties, body: body);
 Console.WriteLine($"{DateTime.Now.ToString()} Send {message} , Priority {messagePriority}");

  

消息顺序消费

生产者发送消息例如 下单消息----》支付消息----》  消息有先后 也就是生产者发送的消息有顺序 将 消息发送到一个队列 同时一个消费者消费就可以保证顺序消费

单活模式 只能有一个消费者消费,多个消费者 其他消费者只能空闲,当正在工作消费者 出现宕机,其他消费者 只能有一个 继续消费  

单活 消费者配置 在队列声明时候 加 参数 x-single-active-consumer

IDictionary<string, object?> dic = base.GetQueueArguments(exchangeName, queueName, GetTTLSeconds());
dic.Add("x-single-active-consumer", true);

Rabbitmq 队列状态 SAC

 

 

posted on 2024-08-01 14:55  是水饺不是水饺  阅读(23)  评论(0)    收藏  举报

导航