SpringBoot整合RabbitMq的简单使用

小流程

导pom

		<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-amqp</artifactId>
        </dependency>

改yml

spring:
  rabbitmq:
    host: 8.131.119.30
    port: 5672
    username: root
    password: root
    publisher-returns: true #开启队列接收确认回调
    publisher-confirms: true #开启mq服务器接收确认回调
    template:
      mandatory: true #只要抵达队列,以异步发送优先回调returns
    listener:
      simple:
        acknowledge-mode: manual #消费端开启手动确认(确认收货)

创建交换机、队列、绑定

1、通过AmqpAdmin创建

 	public String createExchange() {
        /**
         * 创建交换机
         * String name:名称, boolean durable:是否持久化, boolean autoDelete:是否自动删除
         */
        DirectExchange exchange = new DirectExchange("java-exchange",true,false);
        amqpAdmin.declareExchange(exchange);
        System.out.println("创建交换机");
        return "";
    }
	public void createQueue() {
        /**
         * 创建队列
         * String name:名称, boolean durable:持久化, boolean exclusive:排他性, boolean autoDelete:自动删除
         */
        Queue queue = new Queue("java-queue",true,false,false);
        amqpAdmin.declareQueue(queue);
        System.out.println("创建队列");
    }
 	public void createBinding() {
        /**
         * 创建绑定
         * String destination:目的地, Binding.DestinationType destinationType:目的地类型,
         * String exchange:交换机, String routingKey:路由键, @Nullable Map<String, Object> arguments:自定义参数
         */
        Binding binding = new Binding("java-queue",
                Binding.DestinationType.QUEUE,"java-exchange","java-test",null);
        amqpAdmin.declareBinding(binding);
        System.out.println("创建绑定");
    }

2、通过加入IOC容器,Spring自动创建

直接注入bean的形式,让spring自动创建,若rabbitMq中没有则创建,有则不创建,并且rabbitmq中存在时,springbean形式创建的不能覆盖mq中的。

 	@Bean
    public Exchange orderExchange() {
        TopicExchange exchange = new TopicExchange("order-exchange",true,false);
        return exchange;
    }
	@Bean
    public Queue orderReleaseQueue() {
        return new Queue("order.release.queue",
                true, false, false);
    }
 	@Bean
    public Binding orderReleaseBinding() {
        return  new Binding("order.release.queue",
                Binding.DestinationType.QUEUE,
                "order-exchange",
                "order.release.order",
                null);
    }

消息的生产与消费

以下均使用springboot自动装配好的RabbitTemplate

生产

	 /**
     * 消息发送
     * String exchange:交换机
     * String routingKey:路由键
     * Object object:传递的值(可以为对象)
     * CorrelationData correlationData:唯一关联
     */
	public void send() {
        User user = new User();
        user.setAge(22);
        user.setName("name");
        rabbitTemplate.convertAndSend("order-exchange",
                "order.delay.order",
                user,new CorrelationData(UUID.randomUUID().toString()));
    }

消费

@RabbitListener设置监听、该注解使用时必须开启@EnableRabbit

	/**
     * 消息接收
     * @RabbitListener作用:只要监听的队列中有消息,则会自动注入到参数中
     * 消息返回的内容:Body+headers形式
     * 也可以使用消息的类型直接接收,spring可以自动注入到类中
     * Channel:当前连接的通道,消息传输通道
     *
     * Queue可以被很多客户端监听,客户端收到消息,队列中删除
     *      1、一个消息只能被一个客户端收到,
     *      2、一个消息完全处理完才能接收下一个消息
     *
     *   @RabbitListener:可标注在类和方法上
     *   @RabbitHandler:可标注在方法上
     *可联合使用@RabbitHandler(标注方法)+@RabbitListener(标注类)的形式
     * 用@RabbitHandler标注在不同方法上,重载监听不同队列
     */
    @RabbitListener(queues = {"java-queue"}) 
	public void receive(Message msg, User user, Channel channel) {
		//...	
	}

消息确认机制

在这里插入图片描述

生产端确认

  • 开启confirms回调确认:spring.rabbitmq.publisher-confirms= true
  • 当服务端Broker接收到消息后,会回调rabbitTemplate.setConfirmCallback方法
//设置发送端确认回调方法
rabbitTemplate.setConfirmCallback((v1,v2,v3)->{
  /**
    * 消息成功抵达mq中broker服务器则触发
 	* v1:当前消息的唯一关联数据(发送时的correlationData值)
    * v2:消息是否成功收到
    * v3:失败的原因
   */
	System.out.println(v1+"-----"+v2+"---------"+v3);
});

队列抵达确认

  • 开启returns回调:spring.rabbitmq.publisher-returns= true
  • 配合spring.rabbitmq.template.mandatory: true (只要抵达队列,以异步发送优先回调returns)
  • 当消息从交换机Exchange到队列Queue失败时,回调该方法
		rabbitTemplate.setReturnCallback((msg,code,text,exchange,routKey)->{
            /**
             * 消息没有投递给指定队列则触发这个失败回调
             * msg:失败消息的详细信息
             * code:回复的状态码
             * text:回复的文本内容
             * exchang:消息发送给那个交换机
             * routKey:消息的路由键
             */
            System.out.println(msg+"\n"+code+"\n"+text+"\n"+exchange+"\n"+routKey);
        });

消费端确认

开启手动ack
ack:acknowledge(告知已收到)

spring:
  rabbitmq:
	listener:
	      simple:
	        acknowledge-mode: manual #消费端开启手动确认(确认收货)

在消费消息时,手动确认,避免消息丢失

	/**
	 *3、消费端确认(保证每个消息被正确消费,broker才会删除该消息)
     *          默认是自动确认的,消息被接收,客户端自动确认,服务端便会移除这个消息
     *              问题:收到很多消息,自动回复给服务器ack,只有一个消息处理成功,宕机,发生了消息丢失
     *          因此需要给客户端设置手动确认,处理完成在给服务端确认
     *          手动确认模式:
     *              spring.rabbitmq.listener.simple.acknowledge-mode: manual #消费端开启手动确认(确认收货)
     *              channel.basicAck(deliveryTag,false);使用通道手动确认,消息处理完成后确认,服务端删除消息
	*/
	@RabbitListener(queues = {"java-queue"}) //该注解使用时必须开启@EnableRabbit
    public void receive(Message msg, User user, Channel channel) {
        long deliveryTag = msg.getMessageProperties().getDeliveryTag();//当前通道内自增数
        try {
            //手动ack(签收货物) 参数2:是否批量
            channel.basicAck(deliveryTag,false);
        } catch (IOException e) {
            try {
                //退货   v1:自增数  v2:是否批量  v3:重新入队   也可用channel.basicReject();
                channel.basicNack(deliveryTag,false,true);
            } catch (IOException ex) {
                ex.printStackTrace();
            }
            e.printStackTrace();
        }
    }

死信队列(延时队列)的简单使用

简单介绍

  • 死信队列:DLX:dead-letter-exchange
  • 利用DLX,当消息在一个队列中变成死信 (dead message)
    之后,它能被重新publish到另一个Exchange,这个Exchange就是DLX

消息成为死信的几种情况

  1. 队列达到最大长度以后的消息
  2. 消息TTL过期
  3. 被消费端basicNack拒收,重新入队的消息

处理过程

  • DLX也是一个正常的Exchange,和一般的Exchange没有区别,它能在任何的队列上被指定,实际上就是设置某个队列的属性。
  • 当这个队列中有死信时,RabbitMQ就会自动的将这个消息重新发布到设置的Exchange上去,进而被路由到另一个队列。
  • 可以监听这个队列中的消息做相应的处理。

简单使用

在这里插入图片描述
这里我们使用死信队列做延时策略,不监听死信队列,当死信队列中的消息超时后在去消费消息

	@Bean
    public Exchange orderExchange() {
        TopicExchange exchange = new TopicExchange("order-exchange",true,false);
        return exchange;
    }
    
	//死信队列、创建队列时,设置死信交换机,路由键,超时时间等
    @Bean
    public Queue orderDelayQueue() {
        Map<String,Object> arguments = new HashMap<>();
        arguments.put("x-dead-letter-exchange","order-exchange");
        arguments.put("x-dead-letter-routing-key","order.release.order");
        arguments.put("x-message-ttl",60000);
        return new Queue("order.delay.queue",
                true, false, false,arguments);
    }
	//普通队列
    @Bean
    public Queue orderReleaseQueue() {
        return new Queue("order.release.queue",
                true, false, false);
    }

	 @Bean
    public Binding orderDelayBinding() {
        return  new Binding("order.delay.queue",
                Binding.DestinationType.QUEUE,
                "order-exchange",
                "order.delay.order",
                null);
    }
    @Bean
    public Binding orderReleaseBinding() {
        return  new Binding("order.release.queue",
                Binding.DestinationType.QUEUE,
                "order-exchange",
                "order.release.order",
                null);
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值