RabbitMQ使用帮助理解文档

MQ的作用

1.应用的解耦:作为中间件,实现解耦

2.任务异步处理,提高效率

3.削峰填谷:设置消费速度

RabbitMQ相关概念
  • channel:连接;每次访问建立一个连接。创建交换机、队列、设置绑定关系、发送消息,都由这个对象完成
  • exchange:交换机
  • queue:消息队列
  • binding:exchange和queue的虚拟连接规则
RabbitMQ五种模式
  1. 简单模式

    无交换机

  2. work模式

    无交换机,一个队列,多个消费端

  3. 发布订阅模式

    有交换机,多个队列,多个绑定关系,每个队列对应一个消费端;每个队列都收到所有消息

  4. routing路由模式

    升级发布订阅模式:1.交换机类型改为:Direct ; 2.设置绑定消息时指定routing key 3.发送消息时指定routing key

  5. topics主题模式

    升级routing路由模式:1.交换机类型改为:TOPIC;2.设置绑定消息时指定的routing key 使用通配符

springboot整合RabbitMQ步骤
发布端:
  1. 添加依赖

            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-amqp</artifactId>
            </dependency>
  2. 配置RabbitMQ路径信息

    spring:
      rabbitmq:
        host: 192.168.93.5
        port: 5672
        virtual-host: /xzkee
        username: wzyee
        password: wzyee
  3. 创建交换机、队列、绑定关系

    import org.springframework.amqp.core.*; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration;
     
    @Configuration 
    public class RabbitMQConfig {   
        //交换机名称    
        public static final String ITEM_TOPIC_EXCHANGE = "springboot_item_topic_exchange";    //队列名称   
        public static final String ITEM_QUEUE = "springboot_item_queue";
     
        //声明交换机   
        @Bean("itemTopicExchange")  
        public Exchange topicExchange(){   
            return ExchangeBuilder.topicExchange(ITEM_TOPIC_EXCHANGE).durable(true).build();  
        }          //这里使用的topic模式
     
        //声明队列 
        @Bean("itemQueue")   
        public Queue itemQueue(){    
            return QueueBuilder.durable(ITEM_QUEUE).build();  
        }
     
        //绑定队列和交换机  
        @Bean  
        public Binding itemQueueExchange(@Qualifier("itemQueue") Queue queue,                                     @Qualifier("itemTopicExchange") Exchange exchange){        return BindingBuilder.bind(queue).to(exchange).with("item.#").noargs();  
        }
     
    }
  4. 发送消息

      @Autowired   
      private RabbitTemplate rabbitTemplate;
     
      @Test   
      public void test(){                            rabbitTemplate.convertAndSend(RabbitMQConfig.ITEM_TOPIC_EXCHANGE, "item.insert", "商品新 增,routing key 为item.insert");        rabbitTemplate.convertAndSend(RabbitMQConfig.ITEM_TOPIC_EXCHANGE, "item.update", "商品修 改,routing key 为item.update");        rabbitTemplate.convertAndSend(RabbitMQConfig.ITEM_TOPIC_EXCHANGE, "item.delete", "商品删 除,routing key 为item.delete");  
      } 
监听端:1、2两步相同

3.监听

import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;

@Component 
public class MyListener {

  /**    
  * 监听某个队列的消息 
  * @param message 接收到的消息  
  */   
  @RabbitListener(queues = "springboot_item_queue")  
  public void myListener1(String message){  
      System.out.println("消费者接收到的消息为:" + message);  
  } 
}

MQ进阶使用

1.消息投递的可靠性

消息发布端到交换机的回调:1.配置文件开启 确认模式 2. 给rabbitTemplate编写回调函数

交换机到队列的回调:1.配置文件开启 退回模式 2.设置Exchange处理消息失败的模式:setMandatory 3. 给rabbitTemplate编写回调函数

spring:
  rabbitmq:
    publisher-confirms: true
    publisher-returns: true
//在配置类里设置回调函数
@Configuration
public class RabbitConfig{
    @Resource
    private RabbitTemplate rabbitTemplate;
    @Bean
    public RabbitTemplate rabbitTemplate() {
        Logger log = LoggerFactory.getLogger(RabbitTemplate.class);
        
        // 消息确认, yml需要配置 publisher-confirms: true
        rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> {

            if (ack) {
                // log.debug("消息发送到exchange成功,id: {}", correlationData.getId());
            } else {
                log.debug("消息发送到exchange失败,原因: {}", cause);
            }
        });
        
        // 设置交换机处理失败消息的模式, yml需要配置 publisher-returns: true
        rabbitTemplate.setMandatory(true);
        // 消息返回, yml需要配置 publisher-returns: true
        rabbitTemplate.setReturnCallback((message, replyCode, replyText, exchange, routingKey) -> {
            String correlationId = message.getMessageProperties().getCorrelationIdString();
            log.debug("消息:{} 发送失败, 应答码:{} 原因:{} 交换机: {}  路由键: {}", correlationId, replyCode, replyText, exchange, routingKey);
        });
        return rabbitTemplate;
    }
}
2.消费端确认或回退消息

默认为自动确认消息:消费端收到消息后,自动确认并将消息从队列中移除

开启手动确认:业务处理异常可以重新发送消息.

1.在消费端配置文件开启Ack

2.使用channel.basic和Ackchannel.basicNack方法确认

spring:
  rabbitmq:
    listener:
      direct:
        acknowledge-mode: manual
      simple:
        acknowledge-mode: manual #采取手动应答
@Component
@RabbitListener(queues="springboot_item_queue")
public class Consumer2 {
	@RabbitHandler
	public void process(String msg,Channel channel, Message message) throws IOException{
		try {
		    System.out.println("get msg2 success msg = "+msg);
		    //确认收到消息
			channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);	
		} catch (Exception e) {
			//消费者处理出了问题,需要告诉队列信息消费失败,第二个参数表示是否是批量消息,第三个参数表示              是否重回队列
			channel.basicNack(message.getMessageProperties().getDeliveryTag(),
					false, true);
			System.err.println("get msg2 failed msg = "+msg);
		}
	}
}
3.消息限流(配合手动确认使用)

在配置文件配置

spring:
  rabbitmq:
    listener:
      direct:
        acknowledge-mode: manual
      simple:
        acknowledge-mode: manual #采取手动应答
      prefetch: 1   #每次拉取一条消息来消费,直到确认后再拉取消息
4.消息过期时间(TTL)

对队列中的消息设置过期时间,过期自动删除

两种方式:(两种同时使用以时间短的为准)

1.设置队列属性,所有队列所有消息有相同的过期时间

2.对消息单独设置过期时间

    //队列名称   
    public static final String ITEM_QUEUE = "springboot_item_queue";
    @Bean
    public Queue TTlQueue(){
        return QueueBuilder.durable(TTL_QUEUE).withArgument("x-message-ttl", 10000).build();          //单位是毫秒
    }
        //消息处理对象,设置一些消息的参数信息
        MessagePostProcessor messagePostProcessor= new MessagePostProcessor(){

            @Override
            public Message postProcessMessage(Message message) throws AmqpException {
                //设置message的信息
                message.getMessageProperties().setExpiration("5000");//消息的过期时间

                return message;
            }
        };

        rabbitTemplate.convertAndSend(RabbitMQConfig.ITEM_TOPIC_EXCHANGE, "item.delete", "商品删 除,routing key 为item.delete",messagePostProcessor);
5.死信队列
正常交换机、队列 加 另一个交换机(死信交换机)、队列(死信队列)

当原队列中的消息变成死信后,可以重新发送到另一个交换机(死信交换机),

消息变成死信的三种情况:

  1. 原队列消息长度达到限制
  2. 消费者拒收消息,并设置消息不放回原队列(参考上面讲的内容)
  3. 原队列消息过期

配置方式:在声明队列的时候添加参数 x-dead-letter-exchangex-dead-letter-routing-key

值为另一个交换机的名称和绑定关键字


    public static final String NORMAL_DLX_QUEUE = "normal_dlx_queue";
    public static final String NORMAL_DLX_Exchange = "normal_dlx_exchange";
    //ttl
    private static final int NORMAL_DLX_EXPIRATION = 10000;
    //设置队列长度限制
    private static final int NORMAL_DLX_LENGTH = 10;
    public static final String DLX_QUEUE = "dlx_queue";
    public static final String DLX_Exchange = "dlx_exchange";
    //声明原队列,并绑定死信队列
    @Bean
    public Queue normalDlxQueue(){
        return QueueBuilder.durable(NORMAL_DLX_QUEUE)
                .withArgument("x-dead-letter-exchange", DLX_Exchange)
                .withArgument("x-dead-letter-routing-key", "dlx.hehe")
                .withArgument("x-message-ttl", NORMAL_DLX_EXPIRATION)
                .withArgument("x-max-length",NORMAL_DLX_LENGTH)
                .build();
    }

    @Bean
    public TopicExchange normalDlxExchange(){
        return new TopicExchange(NORMAL_DLX_Exchange);
    }

    @Bean
    public Binding normalDlxBinding(){
        return BindingBuilder.bind(normalDlxQueue()).to(normalDlxExchange()).with("test.dlx.#");
    }

    //声明死信队列,和死信交换机
    @Bean
    public Queue dlxQueue(){
        return new Queue(DLX_QUEUE);
    }
    @Bean
    public TopicExchange dlxExchange(){
        return new TopicExchange(DLX_Exchange);
    }
    @Bean
    public Binding dlxBinding(){
        return BindingBuilder.bind(dlxQueue()).to(dlxExchange()).with("dlx.#");
    }
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值