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


浙公网安备 33010602011771号