RabbitMQ——简单模式

简单模式(Simple)

在这一部分中,我们将用Java编写两个程序;
一个是生产者发送单个消息,另一个是接收消息并将其打印出来的消费者。
简单模式
P:生产者;红色部分:队列;C:消费者

The Java client library
RabbitMQ支持多种协议。本教程使用AMQP 0-9-1,它是一种开放的,通用的消息传递协议。
RabbitMQ有许多不同语言的客户端。我们将使用RabbitMQ提供的Java客户端。
下载客户端库及其依赖项(SLF4J API和SLF4J Simple)。
请注意SLF4J Simple足以用于教程,但您应该使用像生产中的Logback这样的完整日志库。
(RabbitMQ Java客户端也位于Maven中央存储库中,包含groupId com.rabbitmq和artifactId amqp-client。)

现在我们有了Java客户端及其依赖项,我们可以编写一些代码。

Sending

Sending

我们消息发布者(sender)定义为对象Send,消息消费者(接收者)定义为对象Recv。发布者将连接到RabbitMQ,发送单个消息,然后退出。
导入相关依赖:

<dependency>
            <groupId>com.rabbitmq</groupId>
            <artifactId>amqp-client</artifactId>
        </dependency>

获取MQ连接:

import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;

public class ConnectionUtils {

    public static Connection getConnection() throws Exception{
        //定义连接工厂
        ConnectionFactory factory=new ConnectionFactory();
        //设置服务地址
        factory.setHost("localhost");
        //设置端口
        factory.setPort(5672);
        //设置账号信息:用户名、密码、vhost
        factory.setVirtualHost("testhost");
        factory.setUsername("admin");
        factory.setPassword("123456");
        //通过工程获取连接
        Connection connection=factory.newConnection();
        return connection;
    }
}

生产者发送消息到队列:

public class Send {
    private final static String QUEUE_NAME="hello";     //命名队列
    public static void main(String[] args) throws Exception{

        try (Connection connection= ConnectionUtils.getConnection(); Channel channel=connection.createChannel()){
            //声明队列
            channel.queueDeclare(QUEUE_NAME,false,false,false,null);
            String message="hello rabbitMQ!";
            channel.basicPublish("",QUEUE_NAME,null,message.getBytes());
            System.out.println("[x] Sent '"+message+"'");
        }
    }
}

获取连接后创建一个频道,这是完成任务的大部分API所在的位置。注意我们可以使用try-with-resources语句,因为Connection和Channel都实现了java.io.Closeable。
这样我们就不需要在代码中明确地关闭它们。

声明队列是幂等的 —— 只有在它不存在的情况下才会创建它。

管理工具中查看消息

Send代码运行之后,可以在管理工具中看到消息
在这里插入图片描述
点击上面的Name对应的名称,查询具体的队列中的信息:

在这里插入图片描述

Receiving

刚才的是发布者(publisher)。我们的消费者应该一直监听来自RabbitMQ的消息,因此与发布单个消息的发布者不同,我们将保持其运行以监听消息并将其打印出来。

receiving
消费者从队列中获取消息:

public class Recv {
    private final static String QUEUE_NAME="hello";

    public static void main(String[] args) throws Exception{
		//获取连接以及频道
        Connection connection= ConnectionUtils.getConnection();
        Channel channel=connection.createChannel();
		//声明队列
        channel.queueDeclare(QUEUE_NAME,false,false,false,null);
        System.out.println(" [*] Waiting for messages. To exit press CTRL+C");
		
        DeliverCallback callback=(consumerTag,delivery)->{
            String message=new String(delivery.getBody(),"UTF-8");
            System.out.println(" [x] Received '" + message + "'");
        };
        //监听队列
        channel.basicConsume(QUEUE_NAME,true,callback,consumerTag->{});
    }
}

请注意,我们也在这里声明了队列。因为我们可能在发布者之前启动消费者,所以我们希望在使用消息之前确保队列存在。

为什么我们这里不使用try-with-resource语句来自动关闭通道和连接?
如果这样做,程序会先运行,然后关闭所有连接,然后退出!这将是尴尬的,因为我们希望在消费者异步监听消息到达时,该进程保持活动状态。

我们要告诉服务器把队列中的消息传递给我。因为它会异步地向我们发送消息,所以我们以对象的形式提供一个回调,它将缓冲消息,直到我们准备好使用它们。这就是DeliverCallback的作用。

### RabbitMQ 的工作模式 RabbitMQ 是一种基于 AMQP 协议的消息中间件,其核心组件包括 **交换器(Exchange)**、**队列(Queue)** 和 **绑定关系(Binding)**。这些组件共同构成了 RabbitMQ 的消息传递机制。 #### 1. 消息传递的核心概念 - **交换器(Exchange)**: 负责接收生产者发送的消息并根据特定规则将消息路由到对应的队列中[^2]。 - **队列(Queue)**: 存储消息的地方,遵循 FIFO 原则。消费者从队列中获取消息进行处理[^3]。 - **绑定关系(Binding)**: 定义了交换器和队列之间的连接规则,决定了哪些消息会被路由到哪个队列。 #### 2. RabbitMQ 的主要工作模式 以下是 RabbitMQ 支持的主要消息传递模式: ##### (1)简单模式(Simple) 在这种模式下,生产者直接向指定的队列发送消息,而无需经过交换器。这是最简单的消息传递方式之一[^1]。 ##### (2)工作队列模式(Work Queue/Task Queue) 多个消费者可以订阅同一个队列中的消息,从而实现负载均衡的效果。每条消息只会被其中一个消费者消费。 ##### (3)发布订阅模式(Publish/Subscribe) 此模式允许一个生产者将消息广播给多个消费者。通过使用 Fanout 类型的交换器,所有与之绑定的队列都会接收到相同的消息副本。 ##### (4)路由模式(Routing) 在路由模式中,生产者发送的消息携带了一个路由键(routing key),交换器会根据这个路由键决定将消息转发至哪一个具体的队列。Direct 类型的交换器就是典型的例子。 ##### (5)主题模式(Topic) 这是一种更高级别的路由形式,在这种情况下,消息不仅可以通过精确匹配的方式到达目标队列,还可以利用通配符来进行模糊匹配。例如,“*”代表任意单个单词;“#”表示零个或多个单词。 #### 3. 死信队列(Dead Letter Exchange, DLX) 当某些条件满足时(如 TTL 到期或者拒绝重新入队),未成功交付的消息会被转移到另一个特殊类型的队列——即所谓的“死信队列”。这一特性有助于监控失败的消息以便后续分析和重试。 ```python import pika connection = pika.BlockingConnection(pika.ConnectionParameters('localhost')) channel = connection.channel() # 创建一个名为 'test_exchange' 的 direct exchange channel.exchange_declare(exchange='test_exchange', exchange_type='direct') # 将队列绑定到 exchange 上,并设置 routing_key result = channel.queue_declare(queue='', exclusive=True) queue_name = result.method.queue channel.queue_bind(exchange='test_exchange', queue=queue_name, routing_key='info') def callback(ch, method, properties, body): print(f"Received {body}") channel.basic_consume(queue=queue_name, on_message_callback=callback, auto_ack=True) print('Waiting for messages...') channel.start_consuming() ``` 上述代码展示了如何声明一个 Direct 类型的交换器并将队列与其绑定的过程。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值