(五)RabbitMQ 消费者确认(消息应答及持久化)

RabbitMQ 消费者消息应答 

消费者应答指的是RabbitMQ需要确认消息到底有没有被收到

当自动应答等于true的时候,表示当消费者一收到消息就表示消费者收到了消息,消费者收到了消息就会立即从队列中删除。

boolean autoAck = false;
channel.basicConsume(QUEUE_NAME,autoAck, consumer);
    /**
     * Start a non-nolocal, non-exclusive consumer, with
     * a server-generated consumerTag.
     * @param queue the name of the queue
     * @param autoAck true if the server should consider messages
     * acknowledged once delivered; false if the server should expect
     * explicit acknowledgements
     * @param callback an interface to the consumer object
     * @return the consumerTag generated by the server
     * @throws java.io.IOException if an error is encountered
     * @see com.rabbitmq.client.AMQP.Basic.Consume
     * @see com.rabbitmq.client.AMQP.Basic.ConsumeOk
     * @see #basicConsume(String, boolean, String, boolean, boolean, Map, Consumer)
     */
    String basicConsume(String queue, boolean autoAck, Consumer callback) throws IOException;

一旦RabbitMQ将消息传递给消费者,RabbitMQ从内存中将消息删除。

如果kill掉正在执行的消费者,消息因为设置为autoAck=true,就会丢失正在处理的消息。

    boolean autoAck = false;
    channel.basicConsume(QUEUE_NAME,autoAck, consumer);

手动模式,如果有一个消费者宕机,RabbitMQ就会把消息发送给其它的消费者,消费者发送一个消息应答,通知RabbitMQ,此消息已经消费完成,可以将内存中的消息删除。

消息应答默认是打开的
 

手动回执消息设置

//手动回执消息
channel.basicAck(envelope.getDeliveryTag(), false);
    /**
     * Acknowledge one or several received
     * messages. Supply the deliveryTag from the {@link com.rabbitmq.client.AMQP.Basic.GetOk}
     * or {@link com.rabbitmq.client.AMQP.Basic.Deliver} method
     * containing the received message being acknowledged.
     * @see com.rabbitmq.client.AMQP.Basic.Ack
     * @param deliveryTag the tag from the received {@link com.rabbitmq.client.AMQP.Basic.GetOk} or {@link com.rabbitmq.client.AMQP.Basic.Deliver}
     * @param multiple true to acknowledge all messages up to and
     * including the supplied delivery tag; false to acknowledge just
     * the supplied delivery tag.
     * @throws java.io.IOException if an error is encountered
     */
    void basicAck(long deliveryTag, boolean multiple) throws IOException;

第一个参数指定 delivery tag,第二个参数说明如何处理这个失败消息。requeue 值为 true 表示该消息重新放回队列头,值为 false 表示放弃这条消息

消息持久化 

    /**
     * Declare a queue
     * @see com.rabbitmq.client.AMQP.Queue.Declare
     * @see com.rabbitmq.client.AMQP.Queue.DeclareOk
     * @param queue the name of the queue
     * @param durable true if we are declaring a durable queue (the queue will survive a server restart)
     * @param exclusive true if we are declaring an exclusive queue (restricted to this connection)
     * @param autoDelete true if we are declaring an autodelete queue (server will delete it when no longer in use)
     * @param arguments other properties (construction arguments) for the queue
     * @return a declaration-confirm method to indicate the queue was successfully declared
     * @throws java.io.IOException if an error is encountered
     */
    Queue.DeclareOk queueDeclare(String queue, boolean durable, boolean exclusive, boolean autoDelete,
                                 Map<String, Object> arguments) throws IOException;

queue:队列名称

durable:是否持久化, 队列的声明默认是存放到内存中的,如果rabbitmq重启会丢失,如果想重启之后还存在就要使队列持久化,保存到Erlang自带的Mnesia数据库中,当rabbitmq重启之后会读取该数据库。

exclusive:是否排外的,有两个作用,一:当连接关闭时connection.close()该队列是否会自动删除;二:该队列是否是私有的private,如果不是排外的,可以使用两个消费者都访问同一个队列,没有任何问题,如果是排外的,会对当前队列加锁,其他通道channel是不能访问的,如果强制访问会报异常

autoDelete:是否自动删除,当最后一个消费者断开连接之后队列是否自动被删除,可以通过RabbitMQ Management,查看某个队列的消费者数量,当consumers = 0时队列就会自动删除

arguments: 队列中的消息什么时候会自动被删除

### RabbitMQ 消费者不消费消息的原因分析 如果遇到RabbitMQ消费者停止消费消息的情况,可能由多种因素引起。理解这些原因有助于采取有效的措施解决问题。 #### 1. 队列配置不当 确保队列已正确声明,并且具有适当属性设置。例如,在某些情况下,持久化队列和非持久化消息组合可能导致性能下降或行为异常[^2]。 #### 2. 消息确认机制问题 默认情况下,自动应答模式下一旦接收到消息即认为已被成功处理;然而,手动应答则允许应用程序控制何时确认消息。若采用后者而忘记调用`basic_ack()`函数,则未被确认消息将继续留在队列中,造成积压现象。 ```python channel.basic_consume(queue='task_queue', on_message_callback=callback, auto_ack=False) def callback(ch, method, properties, body): process_data(body) ch.basic_ack(delivery_tag=method.delivery_tag) # 手动ACK ``` #### 3. 单一消费者瓶颈 单个消费者实例可能会成为整个系统的性能瓶颈,尤其是在面对高并发场景时。此时增加更多消费者可以帮助分担负载,提高整体吞吐量。不过需要注意的是,对于依赖于特定顺序的任务来说,这种方式并不适用,因为它打破了原有的序列关系[^3]。 #### 4. 连接或通道关闭事件 每当有新的消费者加入网络或者现有连接断开重连时,都会触发相应的通知给其他节点。如果频繁发生此类变动,也可能影响到正常的数据流转过程。为了防止这种情况的发生,建议实现心跳检测功能以及合理的错误恢复策略[^4]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值