【RabbitMQ篇】Springboot整合RabbiMQ

1.Springboot整合RabbitMQ

  • 引入amqp依赖场景;RabbitAutoCon>figuration就会自动生
  • 给容器中自动配置了RabbitTemplate、AmqpAdmin、CachingConnectionFactory、RabbitMessagingTemplate
  • @EnableRabbit:(在创建交换机,队列时可以不需要,发送消息可以不需要这个注解,监听消息必须使用这个注解)

1.1导入依赖

        
        
            org.springframework.boot
            spring-boot-starter-amqp
        

1.2rabbit相关配置

spring:
  rabbitmq:
    host: 192.168.234.133
    port: 5672
    virtual-host: /

1.3开启rabbitmq相关功能

@EnableRabbit

1.4整合测试

(1)认识RabbitmqAutoConfiguration

里面自动注入的组件

RabbitTeamplate:用于发送消息
AmqpAdmin:需要一个连接对象
CachingConnectionFactory:连接创建工厂
RabbitMessagingTemplate:操作消息的类
首先就是创建AmqpAdmin,并且这个时候需要配置一下连接工厂的配置信息,主要就是host、port和virtual-host虚拟主机

(2)创建exchange、queue、binding

参数

  • exchange:name、durable(持久化)、autodelete(自动删除)
  • queue:name、durable、excusive(排他,其它连接是否能够传输信息进来)、autodelete
	@Test
    void exchange() {
        //注意,创建交换机就指定了交换机的类型为direct
        DirectExchange directExchange = new DirectExchange("hello.java.exchange",true,false);
        amqpAdmin.declareExchange(directExchange);
    }

    @Test
    void queue() {
        Queue queue = new Queue("hello.java.queue",true,false,true);
        amqpAdmin.declareQueue(queue);
    }

    @Test
    void binding() {
        Binding binding = new Binding("hello.java.queue", Binding.DestinationType.QUEUE,"hello.java.exchange","hello",new HashMap<>());
        amqpAdmin.declareBinding(binding);
    }

(3)发送消息

思路

①第一个就是要知道在传送消息的时候是需要依靠模板rabbitTemplate,它里面有一个messageConverter,这个转换器主要就是能够把消息变成对应的形式。通常用的是simple,这个转换器就是序列化转换成byte数组来传输,但是我们可以增加自己配置一个Json的Config转换器。发送消息用的是json状态

②接着就是通过模板来发送

@Configuration
public class MyRabbitConfig {

    @Bean
    public MessageConverter messageConverter(){
        return new Jackson2JsonMessageConverter();
    }
}

发送消息用例:

	@Autowired
    RabbitTemplate rabbitTemplate;

    @Test
    public void sendMessage(){
        MemberResVo memberResVo = new MemberResVo();
        memberResVo.setCity("sss");
        memberResVo.setId(123L);
        /**
        *	 参数如下:交换机名称、消息的路由键、消息内容、(消息的唯一id:new CorrelationData(UUID.randomUUID().toString))
        */
        rabbitTemplate.convertAndSend("hello.java.exchange","hello",memberResVo);
    }

(4)接收消息

思路

①开启注解EnableRabbit才能够使用@RabbitListener来监听,并且指定监听队列可以是多个。

②然后就发送消息进行测试

RabbitHandler主要只能对方法起作用,@RabbitListener类和方法都可以,但是handler有利于方法的重载:用于接收不同类型的消息

【RabbitMQ篇】Springboot整合RabbiMQ_第1张图片

1.5消息可靠抵达

  • 引入背景

    为保证消息不丢失,可靠抵达,可以使用事务消息,但是性能下降250倍,为此引入确认机制

  • 确认机制

    • confirmCallback 确认模式:确认消息是否到达消息代理

    • returnCallback退回模式:若消息没有传递给指定队列,就触发这个失败回调

    • ack机制:消费者确认模式

      CK机制是消费者从RabbitMQ收到消息并处理完成后,反馈给RabbitMQ,RabbitMQ收到反馈后才将此消息从队列中删除。 如果一个消费者在处理消息出现了网络不稳定、服务器异常等现象,那么就不会有ACK反馈,RabbitMQ会认为这个消息没有正常消费,会将消息重新放入队列中

(1)ConfirmCallback (确认模式:发送端确认)

  • spring.rabbitmq.publisher-confirms=true
    • 在创建 connectionFactory 的时候设置 PublisherConfirms(true) 选项,开启confirmcallback 。
      CorrelationData:用来表示当前消息唯一性。
    • 消息只要被 broker 接收到就会执行 confirmCallback,如果是 cluster 模式,需要所有broker 接收到才会调用 confirmCallback。
    • 被 broker 接收到只能表示 message 已经到达服务器,并不能保证消息一定会被投递到目标 queue 里。所以需要用到接下来的 returnCallback 。
  • 开启配置
spring:
	rabbit:
		publisher-confirms: true
  • 自定义rabbitTemplate,开启确认模式

【RabbitMQ篇】Springboot整合RabbiMQ_第2张图片

(2)ReturnCallback(回退模式:发送端确认)

  • spring.rabbitmq.publisher-returns=true
  • spring.rabbitmq.template.mandatory=true
    • confrim 模式只能保证消息到达 broker,不能保证消息准确投递到目标 queue 里。在有些业务场景下,我们需要保证消息一定要投递到目标 queue 里,此时就需要用到return 退回模式。
    • 这样如果未能投递到目标 queue 里将调用 returnCallback ,可以记录下详细到投递数据,定期的巡检或者自动纠错都需要这些数据。
  • 开启配置
spring:
	rabbit:
		//开启发送端消息抵达Queue确认
		publisher-returns: true
		//只要消息不能抵达queue时,该消息不会被丢弃,而是会被返回给生产者
		template:
			mandatory: true
  • 自定义rabbitTemplate
    【RabbitMQ篇】Springboot整合RabbiMQ_第3张图片

(3)ACK机制

  • 消费者获取到消息,成功处理,可以回复Ack给Broker

    • basic.ack用于肯定确认;broker将移除此消息
    • basic.nack用于否定确认;可以指定broker是否丢弃此消息,可以批量
    • basic.reject用于否定确认;同上,但不能批量
  • 默认自动ack,消息被消费者收到,就会从broker的queue中移除

  • queue无消费者,消息依然会被存储,直到消费者消费

    • 消费者收到消息,默认会自动ack。但是如果无法确定此消息是否被处理完成,或者成功处理。我们可以开启手动ack模式
    • 消息处理成功,ack(),接受下一个消息,此消息broker就会移除
    • 消息处理失败,nack()/reject(),重新发送给其他人进行处理,或者容错处理后ack
    • 消息一直没有调用ack/nack方法,broker认为此消息正在被处理,不会投递给别人,此时客户端断开,消息不会被broker移除,会投递给别人

测试场景:

  • 发送五个消息测试,就算客户端已经拿到了消息,但是没有确认,队列中的消息仍然不能移除,只不过状态由ready变为unacked
  • 此时关闭服务服务,消息的状态由unacked变为ready,下次客户端服务启动又会接收到消息ready变为unacked
  • 除非手动确认
  • 开启手动ack机制
spring:
	listener:
		simple:
			acknowledge-mode: manual

【RabbitMQ篇】Springboot整合RabbiMQ_第4张图片

你可能感兴趣的:(RabbitMQ,java-rabbitmq,rabbitmq,spring,boot,笔记,java,后端,中间件)