生产者端
目录结构
导入依赖
修改yml
业务逻辑
队列消息过期
消息单独过期
TTL(Time To Live)存活时间。表示当消息由生产端存入MQ当中的存活时间,当时间到达的时候还未被消息就会被自动清除。RabbitMQ可以对消息单独设置过期时间也可以对整个队列(并不是队列,而是队列中的消息)设置过期时间。
org.springframework.boot
spring-boot-starter
org.springframework.boot
spring-boot-starter-test
test
org.springframework.boot
spring-boot-starter-amqp
2.5.0
junit
junit
4.12
test
spring:
rabbitmq:
host: localhost
port: 5672
username: guest
password: guest
#三个类型:none默认不开启确认回调 correlated开启确认回调
#simple也会确认回调 还会调用waitForConfirms()方法或waitForConfirmsOrDie()方法
publisher-confirm-type: correlated # 开启确认回调
publisher-returns: true # 开启退回回调
第一段代码即是定义交换机与队列的名称并使其进行绑定,仅是一个配置类的效果。第二段代码就是生产者产生消息的方法,只需要在意for循环里面的逻辑即可。而图1即是创建出来的队列以及生产的10条消息,在10s会自动删除。因为在配置类中已经定义了TTL。
/**
* 定义交换机与队列的Bean 并且使之绑定
*/
@Component
public class RabbitMQConfig {
public static final String TTL_EXCHANGE_NAME = "ttl_exchange_name";
public static final String TTL_QUEUE_NAME = "ttl_queue_name";
@Bean("ttlExchange")
public Exchange ttlExchange(){
return ExchangeBuilder.topicExchange(TTL_EXCHANGE_NAME).durable(true).build();
}
//配置队列的时候顺带上ttl()方法 其内部对MQ设置了参数"x-message-ttl"
//注意这里的单位是毫秒 所以我写的参数为10000毫秒即10秒
@Bean("ttlQueue")
public Queue ttlQueue(){
return QueueBuilder.durable(TTL_QUEUE_NAME).ttl(10000).build();
}
@Bean
public Binding ttl(@Qualifier("ttlExchange") Exchange exchange,
@Qualifier("ttlQueue") Queue queue){
return BindingBuilder.bind(queue).to(exchange).with("test.#").noargs();
}
}
@SpringBootTest
@RunWith(SpringRunner.class)
class RabbitmqProducerApplicationTests {
@Autowired
private RabbitTemplate rabbitTemplate;
@Test
void testTTL(){
rabbitTemplate.setConfirmCallback(new RabbitTemplate.ConfirmCallback() {
@Override
public void confirm(CorrelationData correlationData, boolean b, String s) {
if(b) System.out.println("交换机成功接受到了消息");
else System.out.println("消息失败原因" + s);
}
});
rabbitTemplate.setMandatory(true);
rabbitTemplate.setReturnCallback(new RabbitTemplate.ReturnCallback() {
@Override
public void returnedMessage(Message message, int i, String s, String s1, String s2) {
System.out.println("队列接受不到交换机的消息进行了失败回调");
}
});
// 以上代码只是保证消息传递的可靠性 与TTL无关
for(int i = 0; i < 10; ++i){
rabbitTemplate.convertAndSend(RabbitMQConfig.TTL_EXCHANGE_NAME,"test.heHe","HelloWorld");
}
}
}
图1
这里的配置类还是如上相同:队列中的消息10s自动过期,再对其中一条消息进行处理就可以更好的明白这两种过期的区别:其中一条消息设置了5s自动过期,通过图2可以发现队列中有11条消息,当5s后变为10条消息,再过了5s后就没有消息。
@SpringBootTest
@RunWith(SpringRunner.class)
class RabbitmqProducerApplicationTests {
@Autowired
private RabbitTemplate rabbitTemplate;
@Test
void testTTL(){
rabbitTemplate.setConfirmCallback(new RabbitTemplate.ConfirmCallback() {
@Override
public void confirm(CorrelationData correlationData, boolean b, String s) {
if(b) System.out.println("交换机成功接受到了消息");
else System.out.println("消息失败原因" + s);
}
});
rabbitTemplate.setMandatory(true);
rabbitTemplate.setReturnCallback(new RabbitTemplate.ReturnCallback() {
@Override
public void returnedMessage(Message message, int i, String s, String s1, String s2) {
System.out.println("队列接受不到交换机的消息进行了失败回调");
}
});
// 以上代码只是保证消息传递的可靠性 与TTL无关
// 消息的后处理对象 设置一些消息的参数信息
MessagePostProcessor messagePostProcessor = new MessagePostProcessor(){
@Override
public Message postProcessMessage(Message message) throws AmqpException {
message.getMessageProperties().setExpiration("5000");//设置消息对象5s后过期
return message;
}
};
//消息单独5s过期
rabbitTemplate.convertAndSend(RabbitMQConfig.TTL_EXCHANGE_NAME,"test.heHe","HelloWorld",messagePostProcessor);
//队列中的消息全体10s过期
for(int i = 0; i < 10; ++i){
rabbitTemplate.convertAndSend(RabbitMQConfig.TTL_EXCHANGE_NAME,"test.heHe","HelloWorld");
}
}
}
图2
到这真的就以为结束了吗,当我把for循环的10条消息放到单独过期的消息上面,发现了新大陆:一开始的消息也是如图2所示为11条,但是但是,过了5s后并不会消除一条消息,而是过了10s后将11条全部删除了。于是我猜测这个消息的存放队列就好似一个栈,虽然先生产的消息的生存时间短,但是当别的消息压在自己头上的时候是出不去的,而是必须等自己为栈顶元素才可以出栈!