springboot整合rabbitmq高级特性配置

一.ack模式

ack模式
在 spring boot 中提供了三种确认模式:

NONE - 使用rabbitmq的自动确认
AUTO - 使用rabbitmq的手动确认, springboot会自动发送确认回执 (默认)
MANUAL - 使用rabbitmq的手动确认, 且必须手动执行确认操作
默认的 AUTO 模式中, 处理消息的方法抛出异常, 则表示消息没有被正确处理, 该消息会被重新发送.

spring:
  rabbitmq:
    listener:
      simple:
        # acknowledgeMode: NONE # rabbitmq的自动确认
        acknowledgeMode: AUTO # rabbitmq的手动确认, springboot会自动发送确认回执 (默认)
        # acknowledgeMode: MANUAL # rabbitmq的手动确认, springboot不发送回执, 必须自己编码发送回执

手动执行确认操作
如果设置为 MANUAL 模式,必须手动执行确认操作

@RabbitListener(queues="task_queue")
	public void receive1(String s, Channel c, @Header(name=AmqpHeaders.DELIVERY_TAG) long tag) throws Exception {
		System.out.println("receiver1 - 收到: "+s);
		for (int i = 0; i < s.length(); i++) {
			if (s.charAt(i) == '.') {
				Thread.sleep(1000);
			}
		}
		// 手动发送确认回执
		c.basicAck(tag, false);
	}

二、消费限额

工作模式中, 为了合理地分发数据, 需要将 qos 设置成 1, 每次只接收一条消息, 处理完成后才接收下一条消息.

spring boot 中是通过 prefetch 属性进行设置, 改属性的默认值是 250.

spring:
  rabbitmq:
    listener:
      simple:
        prefetch: 1 # qos=1, 默认250

三、当有多条消息存入到消息队列中时,可实现消费者高并发接收队列消息问题
/**

  • testDirectRabbit 是监听对列的名称
  • concurrency min-max 表示并发数,表示有多少个消费者处理队列里的消息 最小-最大数
    */
    @RabbitListener(queues = “testDirectQueue”,concurrency=“5-10”)
    public class DirectReceiver {
    @RabbitHandler
    public void process(Map testMessage){
    System.out.println(Thread.currentThread().getName()+testMessage.toString());
    }
    }

四、设置消息过期时间TTL
主要有2种方式:

1、指定一条消息的过期时间。
2、给队列设置消息过期时间,队列中的所有消息都有同样的过期时间。

1、指定消息的过期时间(消息推送到队列后,如果指定时间内没有被消费,则会自动过期。)

@RestController
public class TTLController {
    @Autowired
    private RabbitTemplate rabbitTemplate;

    @PostMapping("/testTTL")
    public String testTTL() {
        MessageProperties messageProperties = new MessageProperties();
        messageProperties.setExpiration("20000"); // 设置过期时间,单位:毫秒
        byte[] msgBytes = "测试消息自动过期".getBytes();
        Message message = new Message(msgBytes, messageProperties);
        rabbitTemplate.convertAndSend("TTL_EXCHANGE", "TTL", message);
        return "ok";
    }
}

2、给队列中的所有消息设置过期时间(在队列绑定的时候添加x-message-ttl参数)

@Configuration
public class TTLQueueRabbitConfig {
    @Bean
    public Queue TTLQueue() {
        Map<String, Object> map = new HashMap<>();
        map.put("x-message-ttl", 30000); // 队列中的消息未被消费则30秒后过期
        return new Queue("TTL_QUEUE", true, false, false, map);
    }

    @Bean
    public DirectExchange TTLExchange() {
        return new DirectExchange("TTL_EXCHANGE", true, false);
    }

    @Bean
    public Binding bindingDirect() {
        return BindingBuilder.bind(TTLQueue()).to(TTLExchange()).with("TTL");
    }
}

五、实现延时队列(原理ttl+死信队列就可以实现)
给缓冲队列设置超时时间,而消费者并不从这个缓冲队列中拿消息,这样等消息ttl变成死信队列后就转发给了实际队列,消费者只需要绑定实际队列,从实际队列拿消息,这样就可以实现延时。
在这里插入图片描述

在RabbitMQ的Queue可以配置x-dead-letter-exchange 和x-dead-letter-routing-key(可选)两个参数,如果队列内出现了dead letter,则按照这两个参数重新路由转发死信交换机在发送到指定的队列。

x-dead-letter-exchange:出现dead letter之后将dead letter重新发送到指定exchange
x-dead-letter-routing-key:出现dead letter之后将dead letter重新按照指定的routing-key发送

@Configuration
public class DelayQueueConfig {
     public final static String DELAY_QUEUE_PER_QUEUE_TTL_NAME = "delay_queue_per_queue_ttl";
 
    public final static String DELAY_PROCESS_QUEUE_NAME = "delay_process_queue";
 
    public final static String DELAY_EXCHANGE_NAME = "delay_exchange";
 
    public final static int QUEUE_EXPIRATION = 4000;
 
    @Bean
    Queue delayQueuePerQueueTTL() {
        return QueueBuilder.durable(DELAY_QUEUE_PER_QUEUE_TTL_NAME)
            .withArgument("x-dead-letter-exchange", DELAY_EXCHANGE_NAME) // DLX
            .withArgument("x-dead-letter-routing-key", DELAY_PROCESS_QUEUE_NAME) // dead letter携带的routing key
            .withArgument("x-message-ttl", QUEUE_EXPIRATION) // 设置队列的过期时间
            .build();
    }
 
    @Bean
    Queue delayProcessQueue() {
        return QueueBuilder.durable(DELAY_PROCESS_QUEUE_NAME)
            .build();
    }
 
    @Bean
    DirectExchange delayExchange() {
        return new DirectExchange(DELAY_EXCHANGE_NAME);
    }
 
    @Bean
    Binding dlxBinding(Queue delayProcessQueue, DirectExchange delayExchange) {
        return BindingBuilder.bind(delayProcessQueue)
            .to(delayExchange)
            .with(DELAY_PROCESS_QUEUE_NAME);
    }
}
  • 0
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值