消息确认
在消息队列中,消费者消费了信息,但是却没能成功执行信息中的事务,如果此时消息队列中的消息已经被消费了,那么显然是不可取的。
那么如何保证消息被成功消费了呢?在RabbitMq的消息队列中存在确认机制,我们大致可以将消息队列中的消息分成3种状态。
- 已准备,刚被生产者放入队列消息
- 待确认,被消费者接收的消息,还未发送确认信息
- 已确认消费,消费者接收到消息后发送确认信息
在RabbitMq管理页面中也体现了这三种状态的消息,如果客户端与RabbitMq失去连接,而且消息还没有被确认,那么待确认的消息会重新变成已准备的状态。
注意Total表示的是待确认和已准备的消息数量,不包括已经消费完的数量。
java客户端发送确认信息
- 设置自动确认
在java客户端中接收消息时可以设置时候自动确认,默认是false,就是手动确认。
第二个参数就是设置自动确认属性
- 手动确认
调用basicAck方法
交换机的使用
交换机的类型如下:
- direct
这种类型的交换机的路由规则是根据一个routingKey的标识,交换机通过一个routingKey与队列绑定 ,在生产者生产消息的时候指定一个routingKey,当绑定的队列的routingKey与生产者发送的一样,那么交换机会把这个消息发送给对应的队列。
- fanout
这种类型的交换机路由规则很简单,只要与他绑定了的队列, 他就会把消息发送给对应队列(与routingKey没关系)。
- topic
这种类型的交换机路由规则也是和routingKey有关,只不过topic可以根据*
和#
( *
代表过滤一单词,#
代表过滤后面所有单词, 用.
隔开)来识别routingKey。
假设我绑定的routingKey有队列A和B,A的routingKey是*.user
,B的routingKey是#.user
。
那么我生产一条消息routingKey为error.user
那么此时 2个队列都能接受到, 如果改为topic.error.user
那么这时候,只有B能接受到了。
- headers
这个类型的交换机很少用到,他的路由规则 与routingKey无关 而是通过判断header参数来识别的, 基本上没有应用场景,因为上面的三种类型已经能应付了。
这里只介绍前面三种交换机direct、fanout和topic,需要注意的是这里的匹配都是和交换机和队列相关,是与交换机和队列绑定的时候和发送消息的时候相关。
fanout
交换机直接绑定到队列上,这样只要绑定了交换机的队列都可以接收到数据,与路由键的匹配没有联系。
public static void sendByFanoutExchange(String message) throws Exception {
Connection connection = ConnectionUtil.getConnection();
Channel channel = connection.createChannel();
//声明队列
channel.queueDeclare(ConnectionUtil.QUEUE_NAME,true,false,false,null);
// 声明exchange
channel.exchangeDeclare(ConnectionUtil.EXCHANGE_NAME, "fanout");
//交换机和队列绑定,最后一个参数是路由键
channel.queueBind(ConnectionUtil.QUEUE_NAME, ConnectionUtil.EXCHANGE_NAME, "");
channel.basicPublish(ConnectionUtil.EXCHANGE_NAME, "", null, message.getBytes());
System.out.println("发送的信息为:" + message);
channel.close();
connection.close();
}