RabbitMQ 笔记

来源:互联网 发布:wifi模块远程控制源码 编辑:程序博客网 时间:2024/05/29 05:56

本文出自于EumJi个人博客,仅限于学习用途的转载,转载请注明出处http://www.eumji025.com/article/details/256524

前言

本部分专题是个人学习RabbitMQ的笔记,本篇介绍RabbitMQ的基本概念和使用RabbitMQ实现一个简单的消息队列例子.

本文不介绍安装配置,自行百度.

简介

RabbitMQ是一套开源(MPL)的消息队列服务软件,是由 LShift 提供的一个 Advanced Message Queuing Protocol (AMQP) 的开源实现,由以高性能、健壮以及可伸缩性出名的 Erlang 写成。

​ –摘自维基百科

RabbitMQ作为消息队列,可以接受 并转发消息。您可以把他理解为邮局:将您需要发布的消息放在这个中间件中,最终会被发送给接受方。这些概念比较基础使用过多线程也应该非常熟悉。有点类似生产者和消费者模式,在此就不进行过多的描述。

Rabbit 术语介绍

生产者

生产者往往指的是消息的发送方,在程序中则主要是指发送消息的那部分片段。

队列

队列主要是用来存放生产者推送过来的消息,等待消费者提取消息的中间件。类似于邮局这类中间成员。

这是RabbitMQ的核心部分

消费者

消费者是和上面描述的生产者对立的,主要是消息的接受方。

JAVA演示

RabbitMQ支持多种编程语言(java,python,ruby,C#,PHP。。。),具体参见官方文档。这里主要演示JAVA中的RabbitMQ hello world示例。

环境准备

1.使用java项目需要下载RabbitMQ相关的jar

核心: amqp-client-4.0.2.jar

RabbitMQ的client还依赖slf4j的jar包

依赖: slf4j-api-1.7.21.jar

​ slf4j-simple-1.7.21.jar(缺少此jar无法正确输出)

2.使用maven项目需要如下主要依赖

<!-- https://mvnrepository.com/artifact/com.RabbitMQ/amqp-client -->        <dependency>            <groupId>com.RabbitMQ</groupId>            <artifactId>amqp-client</artifactId>            <version>4.1.0</version>        </dependency>        <!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-api -->        <dependency>            <groupId>org.slf4j</groupId>            <artifactId>slf4j-api</artifactId>            <version>1.7.21</version>        </dependency>        <!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-simple -->        <dependency>            <groupId>org.slf4j</groupId>            <artifactId>slf4j-simple</artifactId>            <version>1.7.21</version>        </dependency>

项目结构图

maven项目机构图

生产者代码

public class Product {    private static Logger logger = LoggerFactory.getLogger(Product.class);    public static final String QUEUE_HELLO = "FIRST_QUEUE";    public static void main(String[] args) {        //1.创建连接工厂        ConnectionFactory factory = new ConnectionFactory();        //2.配置工厂的RabbitMQ server的主机        factory.setHost("localhost");        Connection connection = null;        Channel channel = null;        try {            //3.新建一个连接            connection = factory.newConnection();            //4.获取一个连接频道            channel = connection.createChannel();            /**             * 5.配置一个队列的信息             * 在RabbitMQ中,队列声明是幂等性的(一个幂等操作的特点是其任意多次执行所产生的影响均与一次执行的影响相同)             * 也就是说,如果不存在,就创建,如果存在,不会对已经存在的队列产生任何影响。             * @param queue 队列名称             * @param durable 如果我们声明持久队列(队列将在服务器重新启动后生效),则为true             * @param exclusive 如果我们声明排他队列(限于此连接),则为true             * @param autoDelete 如果我们声明一个自动删除队列,则为true(服务器将在不再使用时将其删除)             * @param arguments 队列的其他属性(构造参数)             */            channel.queueDeclare(QUEUE_HELLO,false,false,false,null);            String message = "Hello World!" ;            /**             * 6.将消息放在队列中(字节数组形式)             * @param exchange 交换发布消息             * @param routingKey 路由密钥             * @param props 消息的其他属性 - 路由头等             * @param body 消息体             */            channel.basicPublish("",QUEUE_HELLO,null,message.getBytes());            System.out.println("product Sent '" + message + "'");        } catch (IOException e) {            logger.error("RabbitMQ发送消息发生IO异常");            e.printStackTrace();        } catch (TimeoutException e) {            logger.error("RabbitMQ发生连接超时异常");            e.printStackTrace();        }finally {            try {                //7.关闭连接                channel.close();                connection.close();            } catch (IOException e) {                logger.error("RabbitMQ关闭发生IO异常");                e.printStackTrace();            } catch (TimeoutException e) {                logger.error("RabbitMQ发生关闭超时异常");                e.printStackTrace();            }        }    }

主要操作步骤在代码中都有注明,有点类似hibernate的操作。理解起来相对简单。只要注意 channel.queueDeclare(QUEUE_HELLO,false,false,false,null)不会每次都新建一个队列,而是先去查询是否存在,若存在则不进行操作。

消费者代码

public class Customer {    private static Logger logger = LoggerFactory.getLogger(Product.class);    public static final String QUEUE_HELLO = "FIRST_QUEUE";    public static void main(String[] args) {        //1.创建连接工厂        ConnectionFactory factory = new ConnectionFactory();        //2.配置工厂的RabbitMQ server的主机        factory.setHost("localhost");        Connection connection = null;        Channel channel = null;        try {            //3.新建一个连接            connection = factory.newConnection();            //4.获取一个连接频道            channel = connection.createChannel();            /**             * 5.声明队列的信息             * 在RabbitMQ中,队列声明是幂等性的(一个幂等操作的特点是其任意多次执行所产生的影响均与一次执行的影响相同)             * 也就是说,如果不存在,就创建,如果存在,不会对已经存在的队列产生任何影响。             * @param queue 队列名称             * @param durable 如果我们声明持久队列(队列将在服务器重新启动后生效),则为true             * @param exclusive 如果我们声明排他队列(限于此连接),则为true             * @param autoDelete 如果我们声明一个自动删除队列,则为true(服务器将在不再使用时将其删除)             * @param arguments 队列的其他属性(构造参数)             */            channel.queueDeclare(QUEUE_HELLO,false,false,false,null);            System.out.println("customer wait  message!!!");            //覆盖DefaultConsumer的handleDelivery方法,回调信息            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,0,body.length,"UTF-8");                    System.out.println(message);                    logger.info("收到productor的消息:"+message);                }            };            channel.basicConsume(QUEUE_HELLO,true,consumer);        } catch (IOException e) {            logger.error("RabbitMQ发送消息发生IO异常");            e.printStackTrace();        } catch (TimeoutException e) {            logger.error("RabbitMQ发生连接超时异常");            e.printStackTrace();        }    }}

消费者的代码和生产者的步骤类似,只是消费者不推送消息,而是去获取消息,需要覆盖DefaultConsumer的handleDelivery方法,进行自己的消息处理。

消费者不要关闭连接,不然将不会进行轮询,直接查询一次后就结束。

演示

首先我们启动是消费者,此时没有消息的推送,消费者等待消息,输出如下:

customer wait  message!!!

然后启动生产者,生产者输出如下:

product Sent 'Hello World!'

然后再查看消费者的控制台,结果如下:

Hello World![pool-1-thread-4] INFO com.eumji.RabbitMQ.Product - 收到productor的消息:Hello World!

RabbitMQ server

经过上面的测试后我们可以在本地RabbitMQ server中查看相关信息 http://localhost:15672/#/

RabbitMQ server state

最后说两句

RabbitMQ的入门例子和多线程中的生产者消费者很类似,大家有兴趣可以去了解一下。
本文原文出自于http://www.rabbitmq.com/tutorials/tutorial-one-java.html
对官方的教程进行部分翻译和修改!!!

与君共勉!!!

参考资料

RabbitMQ官方文档

个人源码

RabbitMQ-helloworld