RabbitMQ
是一个开源的消息中间件,实现了高级消息队列协议(AMQP)标准,用于在应用程序之间传递消息。它提供了可靠的消息传递、消息队列、消息交换、消息路由等功能,使得分布式系统中的各个组件能够进行异步通信。
以下是 RabbitMQ 的一些关键概念:
-
Producer:消息生产者,负责发送消息到 RabbitMQ 的 Exchange(交换机)。
-
Exchange:消息交换机,接收来自 Producer 发送的消息,并根据路由规则将消息路由到一个或多个 Queue(队列)。
-
Queue:消息队列,存储消息直到消费者消费它们。
-
Consumer:消息消费者,从队列中接收消息并进行处理。
-
Binding:绑定,用于将 Exchange 和 Queue 进行绑定,指定消息的路由规则。
-
Routing Key:路由键,用于 Exchange 将消息路由到对应的 Queue。
通过 RabbitMQ,可以实现系统之间的解耦、异步通信、消息传递等功能,提高系统的可靠性和扩展性。在微服务架构中,RabbitMQ常被用于实现服务之间的消息通信,实现事件驱动架构。
java整合rabbit
在 Java 中整合 RabbitMQ 实现消息队列的发送和消费,你可以使用 RabbitMQ 的 Java 客户端库来实现。以下是一个简单的示例,演示了如何使用 Java 客户端库来发送和消费消息:
- 发送消息:
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.Channel;
public class MessageSender {
private final static String QUEUE_NAME = "hello";
public static void main(String[] argv) throws Exception {
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("localhost");
try (Connection connection = factory.newConnection(); Channel channel = connection.createChannel()) {
channel.queueDeclare(QUEUE_NAME, false, false, false, null);
String message = "Hello World!";
channel.basicPublish("", QUEUE_NAME, null, message.getBytes());
System.out.println(" [x] Sent '" + message + "'");
}
}
}
2.消费消息:
import com.rabbitmq.client.*;
public class MessageReceiver {
private final static String QUEUE_NAME = "hello";
public static void main(String[] argv) throws Exception {
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("localhost");
try (Connection connection = factory.newConnection(); Channel channel = connection.createChannel()) {
channel.queueDeclare(QUEUE_NAME, false, false, false, null);
System.out.println(" [*] Waiting for messages. To exit press Ctrl+C");
DeliverCallback deliverCallback = (consumerTag, delivery) -> {
String message = new String(delivery.getBody(), "UTF-8");
System.out.println(" [x] Received '" + message + "'");
};
channel.basicConsume(QUEUE_NAME, true, deliverCallback, consumerTag -> { });
}
}
}
在上述示例中,我们使用了 RabbitMQ 的 Java 客户端库来创建连接、创建通道、声明队列、发送消息以及消费消息。你需要确保你的项目中包含了 RabbitMQ 的 Java 客户端库,并且已经安装并运行了 RabbitMQ 服务器。
Spring Cloud Stream
Spring Cloud Stream 是 Spring Cloud 提供的用于构建消息驱动微服务的框架,而 RabbitMQ 则是其中一个支持的消息中间件。通过 Spring Cloud Stream 结合 RabbitMQ,可以实现微服务之间的消息通信和事件驱动架构。
以下是在 Spring Cloud Stream 中使用 RabbitMQ 的简单示例:
添加依赖: 确保在 pom.xml
文件中添加以下依赖,包括 Spring Cloud Stream 和 RabbitMQ 相关依赖:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-stream-rabbit</artifactId>
</dependency>
配置 RabbitMQ: 在 application.properties
或 application.yml
中配置 RabbitMQ 的连接信息:
spring.cloud.stream.bindings.output.destination=myExchange
spring.cloud.stream.bindings.output.producer.requiredGroups=myGroup
spring.rabbitmq.host=localhost
spring.rabbitmq.port=5672
spring.rabbitmq.username=guest
spring.rabbitmq.password=guest
发送消息: 创建一个消息发送者类,通过 @EnableBinding
注解绑定输出通道,并使用 MessageChannel
发送消息:
import org.springframework.cloud.stream.annotation.EnableBinding;
import org.springframework.cloud.stream.messaging.Source;
import org.springframework.messaging.MessageChannel;
import org.springframework.messaging.support.MessageBuilder;
@EnableBinding(Source.class)
public class MessageSender {
private final MessageChannel output;
public MessageSender(Source source) {
this.output = source.output();
}
public void sendMessage(String message) {
output.send(MessageBuilder.withPayload(message).build());
}
}
消费消息:创建一个消息消费者类,通过 @StreamListener
注解监听输入通道,处理接收到的消息:
import org.springframework.cloud.stream.annotation.StreamListener;
import org.springframework.cloud.stream.messaging.Sink;
import org.springframework.stereotype.Component;
@Component
public class MessageReceiver {
@StreamListener(Sink.INPUT)
public void receiveMessage(String message) {
System.out.println("Received message: " + message);
}
}
通过以上步骤,你可以在 Spring Cloud Stream 中使用 RabbitMQ 实现消息的发送和消费。当消息发送者发送消息时,消费者会监听并接收消息进行处理。你可以根据实际需求进行更复杂的配置和处理。
Channel
RabbitMQ 中的 Channel 是客户端与 RabbitMQ 服务器之间的通信信道,用于发送和接收消息。以下是 RabbitMQ Channel 常用的方法:
-
basicPublish:
- 用于将消息发送到指定的交换机和队列中。
- 方法签名:
basicPublish(String exchange, String routingKey, BasicProperties props, byte[] body)
-
basicConsume:
- 用于从指定的队列中消费消息。
- 方法签名:
basicConsume(String queue, boolean autoAck, Consumer callback)
-
basicAck:
- 用于确认消息已被消费并从队列中移除。
- 方法签名:
basicAck(long deliveryTag, boolean multiple)
-
basicReject:
- 用于拒绝单个消息并选择是否重新放回队列。
- 方法签名:
basicReject(long deliveryTag, boolean requeue)
-
basicNack:
- 用于批量拒绝消息并选择是否重新放回队列。
- 方法签名:
basicNack(long deliveryTag, boolean multiple, boolean requeue)
-
basicGet:
- 用于从指定的队列中获取单个消息。
- 方法签名:
basicGet(String queue, boolean autoAck)
-
basicQos:
- 用于设置消费者的预取数量和预取大小。
- 方法签名:
basicQos(int prefetchCount, int prefetchSize, boolean global)
-
close:
- 用于关闭 Channel。
- 方法签名:
close()
以上是 RabbitMQ Channel 常用的方法
消息的确认机制
在 RabbitMQ 中,消息的确认机制是指消费者在接收并处理消息后向 RabbitMQ 服务器发送确认(acknowledgment)的过程。这个确认机制可以分为自动确认和手动确认两种方式。
-
自动确认(Automatic Acknowledgment):
- 在自动确认模式下,一旦 RabbitMQ 将消息分发给消费者,它会立即将消息标记为已传递。这意味着无论消费者是否成功处理消息,RabbitMQ 都会将消息视为已经被消费。
- 自动确认模式简单且方便,但可能会导致消息丢失,因为如果消费者在处理消息时发生错误,消息将被视为已经被消费,而实际上并没有得到处理。
-
手动确认(Manual Acknowledgment):
- 在手动确认模式下,消费者在处理完消息后,需要显式地向 RabbitMQ 服务器发送确认,告知服务器消息已经被处理。只有在收到确认后,RabbitMQ 才会将消息标记为已经被消费。
- 手动确认模式可以确保消息不会丢失,因为只有在消费者成功处理消息后才会发送确认。这种模式需要消费者编写额外的代码来处理确认逻辑,但可以提供更高的消息处理可靠性。
一般来说,推荐使用手动确认模式,尤其是在需要确保消息不会丢失的情况下。通过手动确认,可以更好地控制消息的处理流程,确保消息被正确处理。
basicAck
channel.basicAck(deliveryTag, true)
是 RabbitMQ 中用于确认消息已被消费并从队列中移除的方法。具体参数含义如下:
deliveryTag
: 表示要确认的消息的交付标签(delivery tag)。- 第二个参数
multiple
设置为true
,表示确认从指定deliveryTag
开始及之前的所有消息。
通过使用 channel.basicAck(deliveryTag, true)
方法,你可以确认消息已被消费并从队列中移除。这个方法通常在消费者成功处理消息后调用,以确保消息被正确处理并且不会再次被消费。
需要注意的是,使用 channel.basicAck
方法确认消息后,消息将被认为已经成功处理,因此不会再次被消费者接收。如果你希望重新将消息放回队列,可以使用 channel.basicNack
方法。
basicNack
channel.basicNack(deliveryTag, true, true)
是 RabbitMQ 中用于批量拒绝消息并重新将消息放回队列的方法。具体参数含义如下:
deliveryTag
: 表示要拒绝的消息的交付标签(delivery tag)。- 第二个参数
multiple
设置为true
,表示拒绝从指定deliveryTag
开始及之前的所有消息。 - 第三个参数
requeue
设置为true
,表示拒绝的消息将重新放回队列,以便重新被消费者接收。
通过使用 channel.basicNack(deliveryTag, true, true)
方法,你可以批量拒绝多个消息并重新将它们放回队列,以便消费者再次接收处理。这种方式可以帮助你处理一次性接收多个消息并重新处理的情况。
basicReject和basicNack的区别
channel.basicReject
和 channel.basicNack
都是 RabbitMQ 中用于拒绝消息的方法,但它们之间有一些区别:
-
channel.basicReject
:channel.basicReject
方法用于拒绝单个消息。- 只能拒绝指定的交付标签(delivery tag)的消息。
- 可以选择是否将被拒绝的消息重新放回队列。
- 不能批量拒绝多个消息。
-
channel.basicNack
:channel.basicNack
方法用于批量拒绝消息。- 可以选择批量拒绝从指定交付标签(delivery tag)开始及之前的所有消息。
- 可以选择是否将被拒绝的消息重新放回队列。
- 支持批量操作,可以一次性拒绝多个消息。
总的来说,channel.basicReject
适用于单个消息的拒绝,而 channel.basicNack
更适合批量拒绝多个消息的场景。根据具体的业务需求和处理逻辑,选择合适的方法来拒绝消息以确保消息队列的正常运作。