一、普通队列
普通队列是最常见的队列类型,消息在队列中按照先进先出(FIFO)的顺序进行传递。当生产者发送消息到普通队列时,消费者可以按照顺序接收和处理这些消息。
(1)依赖引入
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
(2)配置yml文件
spring:
rabbitmq:
host: 127.0.0.1
port: 5672
username: guest
password: guest
virtual-host: /
(3)编写代码实现普通队列
package com.example.springamqp.简单队列;
import org.springframework.amqp.core.Queue;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.rabbit.listener.RabbitListenerEndpointRegistry;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;
@Component
public class RabbitMQManager {
private final RabbitTemplate rabbitTemplate;
@Autowired
public RabbitMQManager(RabbitTemplate rabbitTemplate) {
this.rabbitTemplate = rabbitTemplate;
}
public void sendMessage(String queueName, String message) {
rabbitTemplate.convertAndSend(queueName, message);
}
}
package com.example.springamqp.简单队列;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;
@Component
public class MyCommandLineRunner implements CommandLineRunner {
private final RabbitMQManager rabbitMQManager;
@Autowired
public MyCommandLineRunner(RabbitMQManager rabbitMQManager) {
this.rabbitMQManager = rabbitMQManager;
}
@Override
public void run(String... args) throws Exception {
rabbitMQManager.sendMessage("my_queue", "Hello, RabbitMQ!");
}
@RabbitListener(queues = "my_queue")
public void receiveMessage(String message) {
System.out.println("Received message: " + message);
}
}
(4)结果
二、工作队列
工作队列是 Spring AMQP 中的一个常见队列类型,也被称为任务队列。工作队列用于在多个消费者之间共享和处理任务。工作队列的特点是,生产者将任务消息发送到队列中,多个消费者并发地从队列中接收任务消息并处理。每个任务只会被一个消费者接收和处理,确保任务的唯一性。这种模式可以实现任务的负载均衡和并发处理。
在 Spring AMQP 中,可以使用普通队列来实现工作队列的功能。多个消费者可以同时监听同一个普通队列,当有消息到达队列时,其中一个消费者会接收到消息并处理。可以通过设置消费者数量、消息确认机制和消费者的并发配置来调整工作队列的行为和性能。这样可以确保任务在多个消费者之间分配并按需处理。
(1)依赖引入
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
(2)配置yml文件
spring:
rabbitmq:
host: 127.0.0.1
port: 5672
username: guest
password: guest
virtual-host: /
listener:
simple:
prefetch: 1
默认情况下,Spring AMQP 使用自动消息确认模式(AUTO ACK)来处理消息。在这种模式下,当消费者接收到消息并处理完成后,会自动确认消息,告知 RabbitMQ 该消息已经被成功处理。然而,如果消费者在处理消息时发生错误或出现异常,消息将会丢失,并且无法再次处理。为了提高消息的可靠性和保证不丢失消息,可以通过设置消息预取来控制消费者从队列中获取的消息数量。消息预取允许消费者一次性获取多个消息并进行处理,而不是一次只获取一个消息。这样可以减少消息在网络传输中的开销,并提高消费者的效率。
(3)编写代码实现工作队列
package com.example.springamqp.工作队列;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class WorkRabbitMQManager {
private final RabbitTemplate rabbitTemplate;
@Autowired
public WorkRabbitMQManager(RabbitTemplate rabbitTemplate) {
this.rabbitTemplate = rabbitTemplate;
}
public void sendMessage(String queueName, String message) {
rabbitTemplate.convertAndSend(queueName, message);
}
}
这里将两个linster的sleep时间设置成不一样,可以看出两者的监听情况
package com.example.springamqp.工作队列;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;
@Component
public class WorkCommandLineRunner implements CommandLineRunner {
private final WorkRabbitMQManager rabbitMQManager;
@Autowired
public WorkCommandLineRunner(WorkRabbitMQManager rabbitMQManager) {
this.rabbitMQManager = rabbitMQManager;
}
@Override
public void run(String... args) throws Exception {
for (int i = 0; i < 20; i++) {
rabbitMQManager.sendMessage("my_queue", "Hello, RabbitMQ " + i + "!");
}
}
@RabbitListener(queues = "my_queue")
public void receiveMessage1(String message) throws InterruptedException {
System.out.println("Received1 message: " + message);
Thread.sleep(100);
}
@RabbitListener(queues = "my_queue")
public void receiveMessage2(String message) throws InterruptedException {
System.err.println("Received2 message: " + message);
Thread.sleep(200);
}
}
(4)结果