持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第15天,点击查看活动详情
SpringBoot官方集成了RabbitMQ,所以RabbitMQ与SpringBoot的集成是非常简单的。不过,SpringBoot集成RabbitMQ的方式是按照Spring的一套统一的MQ模型创建的,因此SpringBoot集成插件中对于生产者、消息、消费者等重要的对象模型,与RabbitMQ原生的各个组件有对应关系,但是并不完全相同。
引入依赖
SpringBoot官方集成了RabbitMQ,只需要快速引入依赖包即可使用。RabbitMQ与SpringBoot集成的核心maven依赖就下面一个。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
要特别注意下版本。我们这里采用的是SpringBoot的2.7.0版本的依赖发布包。不同版本下的配置方式会有变化。
配置application.yml
spring:
rabbitmq:
host: 192.168.124.81
port: 5672
username: admin
password: 123456
virtual-host: /mirror
listener:
simple:
# 消费者预处理值
prefetch: 1
# 消费者的消费线程数量
concurrency: 5
# 消费者的最大线程数量
max-concurrency: 10
# 消息确认方式:none 无,manual 手动,auto 自动,默认auto
acknowledge-mode: none
然后所有的基础运行环境都在application.yml中进行配置。所有配置以spring.rabbitmq开头。通常按照示例进行一些基础的必要配置就可以运行。关于详细的配置信息,可以参见RabbitProperties,源码中有各个字段说明。
声明队列
所有的exchange, queue, binding的配置,都需要以对象的方式声明。默认情况下,这些业务对象一经声明,应用就会自动到RabbitMQ上常见对应的业务对象。但是也是可以配置成绑定已有业务对象的。
//声明队列
Queue q1 = new Queue(QUEUE_ANME);
//这种方式可以设置更多参数
Queue q2 = QueueBuilder.durable(QUEUE_NAME).build();
//声明Exchange,可声明交换机CustomExchange,DirectExchange,FanoutExchange,HeadersExchange,TopicExchange
DirectExchange directExchange = new DirectExchange(EXCHANGE_NAME);
//声明Binging
Binding binding = BindingBuilder.bind(q1).to(directExchange);
使用RabbitTemplate发送消息
生产者的所有属性都已经在application.yml配置文件中进行配置。项目启动时,就会在Spring容器中初始化一个RabbitTemplate对象,然后所有的发送消息操作都通过这个对象来进行。
@Autowired
private final RabbitTemplate rabbitTemplate;
public void helloWorld() {
String message = "hello world";
//发消息
rabbitTemplate.send(QUEUE_NAME, new Message(message.getBytes(StandardCharsets.UTF_8)));
}
使用RabbitListener注解声明消费者
消费者都是通过@RabbitListener注解来声明。注解中包含了声明消费者队列时所需要的重点参数。对照原生API,这些参数就不难理解了。
但是当要消费Stream队列时,还是要重点注意他的三个必要的步骤:
channel必须设置basicQos属性。channel对象可以在@RabbitListener声明的消费者方法中直接引用,Spring框架会进行注入。- 正确声明
Stream队列。 通过往Spring容器中注入Queue对象的方式声明队列。在Queue对象中传入声明Stream队列所需要的参数。 - 消费时需要指定
offset。 可以通过注入Channel对象,使用原生API传入offset属性。
SpringBoot集成后的RabbitMQ中的很多概念,虽然都能跟原生API对应上,但是这些模型中间都是做了转换的,比如Message,就不是原生RabbitMQ中的消息了。
@RabbitListener(queues = QUEUE_NAME)
public void classicConsumer(String message) {
log.info(QUEUE_NAME + " receive " + message);
}
关于Stream队列
在目前版本下,使用RabbitMQ的SpringBoot框架集成,可以正常声明Stream队列,往Stream队列发送消息,但是无法直接消费Stream队列了。
关于这个问题,还是需要从Stream队列的三个重点操作入手。SpringBoot框架集成RabbitMQ后,为了简化编程模型,就把channel,connection等这些关键对象给隐藏了,目前框架下,无法直接接入这些对象的注入过程,所以无法直接使用。
如果非要使用Stream队列,那么有两种方式,一种是使用原生API的方式,在SpringBoot框架下自行封装。另一种是使用RabbitMQ的Stream 插件。在服务端通过Strem插件打开TCP连接接口,并配合单独提供的Stream客户端使用。这种方式对应用端的影响太重了,并且并没有提供与SpringBoot框架的集成,还需要自行完善,因此选择使用的企业还比较少。
其实关于Stream队列,现在也不需要着急上手,只是把他当作一种特殊的队列类型,上手了解即可。因为一方面太新的技术,往往还需要小白鼠多多验证。另一方面,现在RabbitMQ多种队列并存的状态,在不久肯定会得到简化,到时候,应用层的使用方式也肯定会跟着变化。