一、前言
Boolean autoAck = false;
channel.basicConsume(queue_name, autoAck ,consumer);
在simple queue 和 work queue(轮询) 处理中,我们设置的消费者的消息监听都采用 channel.basicConsume(queue_name,true, consumer),其中参数二 boolean autoAck为true,但在fair prefetch 公平分发中设置为false,这个设置在整个消息队列和消息消费者之间有什么影响呢?
二、autoAck 参数的讨论
我们都明白一点,autoAck设置为true时,消息队列可以不用在意消息消费者是否处理完消息,一直发送全部消息。但在公平分发中,也就是autoAck设置为false,在发送一个消息后到没收到消息消费者成功消费消息的信息回执之间,是不会继续给这个消息继续发送消息的。
1、当 autoAck设置为true时,也就是自动确认模式,一旦消息队列将消息发送给消息消费者后,就会从内存中将这个消息删除。
2、当autoAck设置为false时,也就是手动模式,如果此时的有一个消费者宕机,消息队列就会将这条消息继续发送给其他的消费者,这样数据在消息消费者集群的环境下,也就算是不丢失了。
在 Boolean autoAck = true的情况下,消息队列不会管消费者是否收到了消息,如果消费者宕机,消息也就丢失了。
在 Boolean autoAck = false的情况下,如果消费者1宕机了,消息队列没有收到消费者发送回的应答,就会将这个消息发送给下一个消费者处理。直到消费者处理完这个消息,并向消息队列发送了一个消息应答,告诉消息队列此时这个消息已经处理完成,消息队列才会将这个消息从内存中删除。
由此我们可以思考一个问题:从上面两个设置中,我们当然会认为false比较好了,但大家可能会忽略一个小问题,消息队列保存的消息是在内存中的,消息队列宕机了,内存中的消息也就清除了,如何做到消息的持久化保存呢?
三、rabbitmq 持久化操作
我们之前在消息的生产者和消息的消费者中都声明了一个消息队列。
channel.queueDeclare(queue_name, false, false, false, null);
他的源码价绍为:
Queue.DeclareOk queueDeclare(String queue,
boolean durable,
boolean exclusive,
boolean autoDelete,
Map<String, Object> arguments) throws IOException;
其中各项参数的含义:
queue:声明队列的名称
durable:如果我们声明一个持久队列,则为true(该队列将在服务器重启后保留下来)
exclusive:如果我们声明一个独占队列,则为true(仅限此连接)
autoDelete:如果我们声明一个自动删除队列(服务器将在不再使用它时将其删除)
arguments:队列的其他属性(构造参数)
小细节:从上面的参数信息中我们发现一个参数durable,发现这个参数是声明队列为持久化队列,那我们改成 true 是否就可以了呢?我们尝试下!
修改send代码中的声明队列:
boolean durable = true;
channel.queueDeclare(queue_name, durable, false, false, null);
运行起来,结果。。
注意:出现这种情况的原因是我的rabbitmq中本身就存在一个设置好了的queue,如下所示:
如果在已存在的消息队列上,依据修改代码变更持久化队列操作,则会出现如上所述的异常信息。
但如果rabbitmq中不存在对应的消息队列时,则不会造成影响。
结论:
rabbitmq不允许对一个已存在的队列重新定义参数信息。
由上面的测试发现:
1、如果在localhost:15672中删除指定的queue,则可以创建出一个持久化队列。
2、重新定义一个网址上不存在的名称作为持久化队列。