按照网上的demo,做了一个rabbitmq的例子,确认模式为手工确认(AcknowledgeMode.MANUAL),但是我的消息发送者,无论消费者是否调用channel.basicAck方法,都会执行到回调函数里。
代码:
配置文件:
@Configuration
public class RabbitConfig {
public static final String EXCHANGE = "exchange";
public static final String ROUTINGKEY = "will.message";
@Autowired
Receiver receiver;
@Bean
public ConnectionFactory connectionFactory() {
CachingConnectionFactory connectionFactory = new CachingConnectionFactory();
connectionFactory.setAddresses("10.120.1.148");
connectionFactory.setUsername("zhouyou");
connectionFactory.setPassword("zhouyou@163");
connectionFactory.setVirtualHost("/");
connectionFactory.setPublisherConfirms(true); //必须要设置
return connectionFactory;
}
@Bean
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
//必须是prototype类型
public RabbitTemplate rabbitTemplate() {
RabbitTemplate template = new RabbitTemplate(connectionFactory());
return template;
}
@Bean
public DirectExchange defaultExchange() {
return new DirectExchange(EXCHANGE);
}
@Bean
public Queue queue() {
return new Queue("will.message", true,false,false,null); //队列持久
}
@Bean
public Binding binding() {
return BindingBuilder.bind(queue()).to(defaultExchange()).with(RabbitConfig.ROUTINGKEY);
}
@Bean
public SimpleMessageListenerContainer messageContainer() {
SimpleMessageListenerContainer container = new SimpleMessageListenerContainer(connectionFactory());
container.setQueues(queue());
container.setExposeListenerChannel(true);
container.setMaxConcurrentConsumers(10);
container.setConcurrentConsumers(1);
container.setAcknowledgeMode(AcknowledgeMode.MANUAL); //设置确认模式手工确认
container.setMessageListener(receiver);
return container;
}
}
消费者receiver:
@Service
public class Receiver implements ChannelAwareMessageListener{
@Override
public void onMessage(Message message, Channel channel) throws Exception {
byte[] body = message.getBody();
System.out.println("receive msg : " + new String(body));
// channel.basicAck(message.getMessageProperties().getDeliveryTag(),false );
}
}
消息发送方sender:@Service
public class Sender implements RabbitTemplate.ConfirmCallback {
private RabbitTemplate rabbitTemplate;
/**
* 构造方法注入
/
@Autowired
public Sender(RabbitTemplate rabbitTemplate) {
this.rabbitTemplate = rabbitTemplate;
rabbitTemplate.setConfirmCallback(this); //rabbitTemplate如果为单例的话,那回调就是最后设置的内容
}
public void sendMsg(String content) {
CorrelationData correlationId = new CorrelationData(UUID.randomUUID().toString());
rabbitTemplate.convertAndSend(RabbitConfig.EXCHANGE, RabbitConfig.ROUTINGKEY, content, correlationId);
}
/*
* 回调
*/
@Override
public void confirm(CorrelationData correlationData, boolean ack, String cause) {
System.out.println(" 回调id:" + correlationData);
if (!ack) {
System.out.println("消息成功消费");
} else {
System.out.println("消息消费失败:" + cause);
}
}
}
测试方法
@Autowired
private Sender sender;
@RequestMapping("/getUserInfo")
@ResponseBody
public void getUserInfo() {
sender.sendMsg("will.message");
}
网页访问地址:
localhost:8080/getUserInfo。
现在问题就是:Receiver里面无论是否调用channel.basicAck(message.getMessageProperties().getDeliveryTag(),false ); 该方法,最后程序都会跑到Sender的confirm方法里面(即 public void confirm(CorrelationData correlationData, boolean ack, String cause) 方法,而且参数ack一直为true)。
求大神告知,是我理解的回调设置错误,还是怎么回事?谢谢!!!!!!
按照我自己的理解,设置为手工确认的时候,
那么需要调用channel.basicAck()方法,才会到回调函数里面去。求解答啊
rabbitmq 手工确认的问题?求大神告知
- 写回答
- 好问题 0 提建议
- 追加酬金
- 关注问题
- 邀请回答
-
3条回答 默认 最新
- brysj_123 2016-10-30 06:48关注
手动确认一般是用来保持事物一致性,在确认客户端将消息消费后,程序回执给rabbitmq server端。server端将消息从server队列中删除。也就是不管你是否设置自动确认,消息一旦发出,都会到达client端
解决 无用评论 打赏 举报
悬赏问题
- ¥30 这是哪个作者做的宝宝起名网站
- ¥60 版本过低apk如何修改可以兼容新的安卓系统
- ¥25 由IPR导致的DRIVER_POWER_STATE_FAILURE蓝屏
- ¥50 有数据,怎么建立模型求影响全要素生产率的因素
- ¥50 有数据,怎么用matlab求全要素生产率
- ¥15 TI的insta-spin例程
- ¥15 完成下列问题完成下列问题
- ¥15 C#算法问题, 不知道怎么处理这个数据的转换
- ¥15 YoloV5 第三方库的版本对照问题
- ¥15 请完成下列相关问题!