rabbitmq消息发送接收确认

建立连接
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;

ConnectionFactory factory = new ConnectionFactory();
factory.setHost("127.0.0.1");
factory.setPort(5672);
factory.setUsername("guest");
factory.setPassword("guest");
conn = factory.newConnection();
channel = conn.createChannel();

建立连接和连接数据库类似。设置ip端口,用户名密码。后续所有的操作都是基于channel上。

发送消息
String QUEUE_NAME = "first";
String message = "hello";
       /*
		 * 参数一:交换机名称,空串表示默认交换机。会投递到与routeKey名称一致的队列
		 * 参数二:routeKey
		 * 参数三:消息属性
		 * 参数四:消息内容
		 * 所以该消息会相当于直接投递到QUEUE_NAME队列中
		 */
channel.basicPublish("", QUEUE_NAME, null, message.getBytes());
接收消息
import com.rabbitmq.client.AMQP.BasicProperties;
import com.rabbitmq.client.DefaultConsumer;
import com.rabbitmq.client.Envelope;
/*
		 * 参数一:队列名
		 * 参数二:是否自动确认,这里设置成false在具体consumer里确认
		 * 参数三:指定消息consumer
		 */
channel.basicConsume(QUEUE_NAME,true,new DefaultConsumer(channel) {
			@Override
			public void handleDelivery(String consumerTag, Envelope envelope, 		                      BasicProperties properties, byte[] body)throws IOException {
                //手动确认消息
				System.out.println("receive message:"+new String(body));
			}
		});
消息发送确认

消息的可靠投递。发送消息时确认消息是成功投递到broker。

//启用发布者确认
channel.confirmSelect();
//绑定确认回调
channel.addConfirmListener(new ConfirmListener() {
@Override
public void handleNack(long deliveryTag, boolean multiple) throws IOException {
        System.out.println("broker接收消息失败");
    }
    @Override
    public void handleAck(long deliveryTag, boolean multiple) throws IOException 			 {
        System.out.println("broker接收消息成功");
    }
});
String msg = "hello";
channel.basicPublish("", QUEUE_NAME, null, msg.getBytes());

绑定一个确认监听器,当消息投递完后,rabbitmq会回调对应的方法。成功调用handleAck方法,失败调用handleNack方法。

消息接收确认
//第二个参数指定是否自动确认
channel.basicConsume(String queue, boolean autoAck, Consumer callback) 

如果开启自动确认,消费者拿走消息后默认消息就被消费。如果设置成false就要在处理消息时手动进行确认消息。

channel.basicConsume(QUEUE_NAME,false,new DefaultConsumer(channel) {
			@Override
			public void handleDelivery(String consumerTag, Envelope envelope, BasicProperties properties, byte[] body)
					throws IOException {
				System.out.println("receive message:"+new String(body));
				/**
				 * 手动确认消息
				 * 参数一:消息标签
				 * 参数二:是否针对多个消息,false只针对当前消息
				 */
				channel.basicAck(envelope.getDeliveryTag(), false);
                /**
				 * 拒绝消息,一次只能拒绝一条
				 * 参数一:消息标签
				 * 参数三:是否将消息重新投递到队列,
				 */
                channel.basicReject(deliveryTag, requeue);
				/**
				 * 手动拒绝消息
				 * 参数一:消息标签
				 * 参数二:是否针对多个消息,false只针对当前消息
				 * 参数三:是否将消息重新投递到队列,
				 *		  false丢弃消息
				 * 	      如果设置为true,当测试只有本一个消费者时就发生死循环了。
				 *        因为重新投递又被自己拿到了又重新投递
				 */
				channel.basicNack(envelope.getDeliveryTag(), false, true);
			}
		});

如果不设置自动确认,拿到消息后又未执行ack消息确认,那么该条消息就会变成unacked状态。这条消息会一直是unacked状态,其他消费者也拿不到。只有当当前消费者断开channel连接。rabbitmq才会认为该条消息未被成功处理,又被重新回收变成ready状态。其它消费者才能再取到该条消息。

我也不知道basicReject和basicNack有什么区别。

在这里插入图片描述

接收设置QoS

prefetchCount

Channel Prefetch Setting:消费者予获取消息的数量。

//consumer级别设置
channel.basicQos(int prefetchCount)
//第二个参数设置true表示channel级别    
channel.basicQos(int prefetchCount, boolean global)

查看源码basicQos(prefetchCount)会调用 basicQos(prefetchCount,false)。

只有消息消费模式为非自动确认模式Qos参数值才有效。

The value defines the max number of unacknowledged deliveries that are permitted on a channel. Once the number reaches the configured count, RabbitMQ will stop delivering more messages on the channel unless at least one of the outstanding ones is acknowledged

这个参数设置channel中最大未确认消息数。当设置为0时就是不限制。当达到这个最大值时,rabbitmq会停止往该channel发送消息。直到有未被确认的消息执行ack后。例一个channel设置Qos为3,当consumer有三条消息未确认后,就不会有新的消息传送给该consumer。如果是因为程序异常导致未执行到消息channel.basicAck方法,试想下这个消费者其实就已经阻塞了,废掉了。3个坑位都被异常消息占了,永远也确认不了。所以消息消费的逻辑一定要处理好。

例1: consumer级别

channel.basicQos(10); // Per consumer limit
channel.basicConsume(queue, false, consumer1);
channel.basicConsume(queue, false, consumer2);

每个consumer最大未确认消息数10.

*例2:*consumer级别和channel级别混用

channel.basicQos(10, false); // consumer级别设置最大10
channel.basicQos(15, true);  // channel级别设置最大15
channel.basicConsume(queue, false, consumer1);
channel.basicConsume(queue, false, consumer2);

这样这两个consumer合计未确认消息数(也就是整个通道)是15。同时每个consumer最大还不能超过10。这样rabbitmq就需要一直协调这两个consumer来遵守这两个原则。会导致性能打折扣。

参考

https://www.rabbitmq.com/consumers.html

https://www.rabbitmq.com/confirms.html

https://www.rabbitmq.com/consumer-prefetch.html

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值