01 前言
今天介绍RabbitMQ,并理解其底层原理。
![](https://i-blog.csdnimg.cn/blog_migrate/8884b588af10d84707bc204e844e9d99.png)
推荐学习1:消息中间件合集:MQ(ActiveMQ/RabbitMQ/RocketMQ)+Kafka+笔记
02 介绍
RabbitMQ是由erlang语言开发,基于AMQP(Advanced Message Queue 高级消息队列协议)协议实现的消息队列。
为什么使用RabbitMQ呢?
- 使得简单,功能强大。
- 基于AMQP协议。
- 社区活跃,文档完善。
- 高并发性能好,这主要得益于Erlang语言。
- Spring Boot默认已集成RabbitMQ
03 AMQP协议
3.1 AMQP基本介绍
AMQP,即Advanced Message Queuing Protocol,一个提供统一消息服务的应用层标准高级消息队列协议,是应用层协议的一个开放标准,为面向消息的中间件设计。基于此协议的客户端与消息中间件可传递消息,并不受客户端/中间件同产品、不同的开发语言等条件的限制。
AMQP的实现有:RabbitMQ、OpenAMQ、Apache Qpid、Redhat Enterprise MRG、AMQP Infrastructure、ØMQ、Zyre等。
目前Rabbitmq最新的版本默认支持的是AMQP 0-9-1,该协议总共包含了3部分:
Module Layer: 位于协议的最高层,主要定义了一些供客户端调用的命令,客户端可以利用这些命令实现自定义的业务逻辑。
例如,客户端可以是使用Queue.Declare命令声明一个队列或者使用Basic.Consume订阅消费一个队列中的消息。
Session Layer: 位于中间层,主要负责将客户端的命令发送给服务端,再将服务端的应答返回给客户端,主要为客户端与服务器之间的通信提供可靠性的同步机制和错误处理。
Transport Layer: 位于最底层,主要传输二进制数据流,提供帧的处理、信道的复用、错误检查和数据表
示等。
3.2 AMQP生产者流转过程
当客户端与Broker建立连接的时候,客户端会向Broker发送一个Protocol Header 0-9-1的报文头,以此通知Broker本次交互才采用的是AMQP 0-9-1协议。
紧接着Broker返回Connection.Start来建立连接,在连接的过程中涉及Connection.Start/.Start-OK、Connection. Tune/. Tune-OK、Connection.Open/.Open-OK这6个命令的交互。
连接建立以后需要创建通道,会使用到Channel.Open , Channel.Open-OK命令,在进行交换机声明的时候需要使用到Exchange.Declare以及Exchange.Declare-OK的命令。以此类推,在声明队列以及完成队列和交换机的绑定的时候都会使用到指定的命令来完成。
在进行消息发送的时候会使用到Basic.Publish命令完成,这个命令还包含了Conetent-Header和Content-Body。Content Header里面包含的是消息体的属性,Content-Body包含了消息体本身。
3.3 AMQP消费者流转过程
消费者消费消息的时候,所涉及到的命令和生成者大部分都是相同的。在原有的基础之上,多个几个命令:Basic.Qos/.Qos-OK以及Basic.Consume和Basic.Consume-OK。
其中Basic.Qos/.Qos-OK这两个命令主要用来确认消费者最大能保持的未确认的消息数时使用。Basic.Consume和Basic.Consume-OK这两个命令主要用来进行消息消费确认。
04 RabbitMQ的特性
RabbitMQ使用Erlang语言编写,使用Mnesia数据库存储消息。
(1)可靠性(Reliability) RabbitMQ 使用一些机制来保证可靠性,如持久化、传输确认、发布确认。
(2)灵活的路由(Flexible Routing) 在消息进入队列之前,通过Exchange 来路由消息的。对于典型的路由功能,RabbitMQ 已经提供了一些内置的Exchange 来实现。针对更复杂的路由功能,可以将多个Exchange 绑定在一起,也通过插件机制实现自己的Exchange。
(3)消息集群(Clustering) 多个RabbitMQ 服务器可以组成一个集群,形成一个逻辑Broker 。
(4)高可用(Highly Available Queues) 队列可以在集群中的机器上进行镜像,使得在部分节点出问题的情况下队列仍然可用。
(5)多种协议(Multi-protocol) RabbitMQ 支持多种消息队列协议,比如AMQP、STOMP、MQTT 等等。
(6)多语言客户端(Many Clients) RabbitMQ 几乎支持所有常用语言,比如Java、.NET、Ruby、PHP、C#、JavaScript 等等。
(7)管理界面(Management UI) RabbitMQ 提供了一个易用的用户界面,使得用户可以监控和管理消息、集群中的节点。
(8)插件机制(Plugin System)RabbitMQ提供了许多插件,以实现从多方面扩展,当然也可以编写自己的插件。
05 工作模型
![](https://i-blog.csdnimg.cn/blog_migrate/78db9798df803518859a89591a62c1e6.png)
名词解释
Broker :即RabbitMQ的实体服务器。提供一种传输服务,维护一条从生产者到消费者的传输线路,保证消息数据能按照指定的方式传输。
Exchange :消息交换机。指定消息按照什么规则路由到哪个队列Queue。
Queue :消息队列。消息的载体,每条消息都会被投送到一个或多个队列中。
Binding :绑定。作用就是将Exchange和Queue按照某种路由规则绑定起来。
Routing Key:路由关键字。Exchange根据Routing Key进行消息投递。定义绑定时指定的关键字称为Binding Key。
Vhost:虚拟主机。一个Broker可以有多个虚拟主机,用作不同用户的权限分离。一个虚拟主机持有一组Exchange、Queue和Binding。
Producer:消息生产者。主要将消息投递到对应的Exchange上面。一般是独立的程序。
Consumer:消息消费者。消息的接收者,一般是独立的程序。
Connection:Producer 和Consumer 与Broker之间的TCP长连接。
Channel:消息通道,也称信道。在客户端的每个连接里可以建立多个Channel,每个Channel代表一个会话任务。在RabbitMQ Java Client API中,channel上定义了大量的编程接口。
5.1 交换机类型
Direct Exchange 直连交换机
定义:直连类型的交换机与一个队列绑定时,需要指定一个明确的binding key。
路由规则:发送消息到直连类型的交换机时,只有routing key跟binding key完全匹配时,绑定的队列才能收到消息。
![](https://i-blog.csdnimg.cn/blog_migrate/d1dea927024f60ee63fd482f8f5b4237.png)
Topic Exchange 主题交换机
定义:主题类型的交换机与一个队列绑定时,可以指定按模式匹配的routing key。
通配符有两个,*代表匹配一个单词。#代表匹配零个或者多个单词。单词与单词之间用 . 隔开。
路由规则:发送消息到主题类型的交换机时,routing key符合binding key的模式时,绑定的队列才能收到消息。
// 只有队列1能收到消息
channel.basicPublish("MY_TOPIC_EXCHANGE", "sh.abc", null, msg.getBytes());
// 队列2和队列3能收到消息
channel.basicPublish("MY_TOPIC_EXCHANGE", "bj.book", null, msg.getBytes());
// 只有队列4能收到消息
channel.basicPublish("MY_TOPIC_EXCHANGE", "abc.def.food", null, msg.getBytes());
![](https://i-blog.csdnimg.cn/blog_migrate/668e921ce7c04d706029442ffe2ad81e.png)
Fanout Exchange 广播交换机
定义:广播类型的交换机与一个队列绑定时,不需要指定binding key。
路由规则:当消息发送到广播类型的交换机时,不需要指定routing key,所有与之绑定的队列都能收到消息。
![](https://i-blog.csdnimg.cn/blog_migrate/717f42ad1458644de0c0328ac26e0a95.png)
06 RabbitMq安装
下载镜像
docker pull rabbitmq
创建并启动容器
docker run -d --name rabbitmq -p 5672:5672 -p 15672:15672 -v `pwd`/data:/var/lib/rabbitmq --hostname myRabbit -e RABBITMQ_DEFAULT_VHOST=my_vhost -e RABBITMQ_DEFAULT_USER=admin -e RABBITMQ_DEFAULT_PASS=admin rabbitmq
- -d 后台运行容器;
- --name 指定容器名;
- -p 指定服务运行的端口(5672:应用访问端口;15672:控制台Web端口号);
- -v 映射目录或文件;
- --hostname 主机名(RabbitMQ的一个重要注意事项是它根据所谓的 “节点名称” 存储数据,默认为主机名);
- -e 指定环境变量;(RABBITMQ_DEFAULT_VHOST:默认虚拟机名;RABBITMQ_DEFAULT_USER:默认的用户名;RABBITMQ_DEFAULT_PASS:默认用户名的密码)
启动rabbitmq后台管理服务
docker exec -it rabbitmq rabbitmq-plugins enable rabbitmq_management
访问后台页面:
http://127.0.0.1:15672 初始密码: admin admin
![](https://i-blog.csdnimg.cn/blog_migrate/1fa94a4d9ba54b82130dda3e4d5f81cb.png)
07 RabbitMQ快速入门
maven依赖
<dependencies>