第一节 RabbitMQ生产者消费者

一、基本模型

        P是就是生产者,就是生产出消息的一方。

        队列就是传输媒介,可理解为传输的管道。可理解为邮递员,邮递员会把把消息投递给收信人。

        C是消费者,用于接收消息,可理解为收信人。

        这就是最简单的消息模型。

二、使用代码

         首先运行接收端的代码,它是一个阻塞方法,会一直等待发送端的消息。

         然后再运行发送端的代码,发送"我养你啊"的消息。

代码步骤

        第一步  让RabbimtMQ服务器与我们的应用程序产生一条可靠的连接

        第二步  通过连接创建一个传输消息的"信道"。

        第三步  通过信道创建队列、路由器等。

        第四步  生产者向信道发送消息。信道会将消息通过队列等保存。

        第五步  消费者从信道接收消息。信道会取出队列中的数据,投递给消费者。

发送端代码。

package com.rabbitmq.helloworld.demo;

import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * @author jay.zhou
 * @date 2019/4/22
 * @time 16:46
 * 生产者
 */
public class Producer {
    private static final String QUEUE_NAME = "local::queue:01";
    private static final Logger LOGGER = LoggerFactory.getLogger(Producer.class);

    public static void main(String[] args) {
        try {
            //连接管理器:我们的应用程序与RabbitMQ建立连接的管理器。
            ConnectionFactory factory = new ConnectionFactory();
            //设置RabbitMQ服务器地址
            factory.setHost("127.0.0.1");
            //设置帐号密码,默认为guest/guest,所以下面两行可以省略
            factory.setUsername("guest");
            factory.setPassword("guest");

            //新建一个连接
            Connection connection = factory.newConnection();
            //再创建一个信道,这个就相当于一个邮局
            //它是消息推送使用的通道。
            Channel channel = connection.createChannel();

            //首先在通道中申明一个队列
            /**
             * 第一个参数是queue:要创建的队列名
             * 第二个参数是durable:是否持久化。如果为true,可以在RabbitMQ崩溃后恢复消息
             * 第三个参数是exclusive:true表示一个队列只能被一个消费者占有并消费
             * 第四个参数是autoDelete:true表示服务器不在使用这个队列是会自动删除它
             * 第五个参数是arguments:其它参数
             */
            channel.queueDeclare(QUEUE_NAME, true, false, false, null);
            //创建一条消息
            String message = "我养你啊!";
            //采用二进制流的方式传输
            byte[] msg = message.getBytes("UTF-8");
            //channel是一个邮局,它接收到msg数据,并将放入到QUEUE_NAME队列中
            channel.basicPublish("", QUEUE_NAME, null, msg);

            LOGGER.info("发送端发送消息:{}",message);
            channel.close();
            connection.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

 

接收端代码。

package com.rabbitmq.helloworld.demo;

import com.rabbitmq.client.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;

/**
 * @author jay.zhou
 * @date 2019/4/22
 * @time 16:53
 */
public class MsgConsumer {
    private static final String QUEUE_NAME = "local::queue:01";
    private static final Logger LOGGER = LoggerFactory.getLogger(MsgConsumer.class);

    public static void main(String[] args) {
        try {
            //连接管理器:我们的应用程序与RabbitMQ建立连接的管理器。
            ConnectionFactory factory = new ConnectionFactory();
            //设置RabbitMQ服务器地址
            factory.setHost("127.0.0.1");

            //新建一个连接
            Connection connection = factory.newConnection();
            //再创建一个信道,这个就相当于一个邮局
            Channel channel = connection.createChannel();

            //首先在通道中申明一个队列
            /**
             * 第一个参数是queue:要创建的队列名
             * 第二个参数是durable:是否持久化。如果为true,可以在RabbitMQ崩溃后恢复消息
             * 第三个参数是exclusive:true表示一个队列只能被一个消费者占有并消费
             * 第四个参数是autoDelete:true表示服务器不在使用这个队列是会自动删除它
             * 第五个参数是arguments:其它参数
             */
            channel.queueDeclare(QUEUE_NAME, true, false, false, null);

            //创建消费者,并重写如何消费的方法,我们这里仅仅就是打印一下消息啦
            //首先从信道里面获取数据
            Consumer consumer = new DefaultConsumer(channel) {
                @Override
                public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body)
                        throws IOException {
                    String message = new String(body, "UTF-8");
                    LOGGER.info("收件人收到消息:{}", message);
                }
            };

            //收到了消息后,提示邮局,我已经收到消息了。可以给我发送其它消息
            //第二个参数autoAck如果为false,那么消息会一直保存在RabbimtMQ服务器
            //消费者没有确认消息被消费,消息一直留在队列中,只有当从有新的消费者加入时,消息被分发到新的消费者。
            channel.basicConsume(QUEUE_NAME, true, consumer);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

三、自动确认autoAck

        在接收端的代码的最后一句:

channel.basicConsume(QUEUE_NAME, true, consumer);

       第二个参数是自动确认。第二个参数autoAck如果为false,那么消息会一直保存在RabbimtMQ服务器。

       运行三次发送端。访问http://localhost:15672,登录guest/guest可以查看拿到这个队列目前已经被投递的消息。

        然后我们再运行几次接收端。

        每次运行接收端,都会收到三次"我养你啊"的消息。原因是,因为接收端没有确认这个消息已经被消费。所以,RabbitMQ会将消息一直保存在消息队列中。上面的Ready数值一直是3,说明消息还保存在RabbitMQ服务器中。

         最后再将代码的autoAck改为true,再运行一次接收者类。队列的Ready属性变成0,说明之前的消息已经被成功消费掉。RabbitMQ服务器最终将这些消息移除。你可以亲自尝试一下哦。

四、源代码下载

        源代码地址:https://github.com/hairdryre/Study_RabbitMQ

        下一篇:第二节 Fanout路由交换机:订阅发布模式

         阅读更多:从头开始学RabbimtMQ目录贴

posted @ 2022-07-17 12:14  小大宇  阅读(322)  评论(0编辑  收藏  举报