RabbitMQ定义
RabbitMQ是实现了高级消息队列协议(AMQP)的开源消息代理软件,亦称面向消息的中间件。
RabbitMQ是一个开源的AMQP实现,服务器端用Erlang语言编写,支持多种客户端。
RabbitMQ特点
1.可靠性:
RabbitMQ使用一些机制来保证可靠性, 如持久化、传输确认及发布确认等。
2.灵活的路由 :
在消息进入队列之前,通过交换器来路由消息。对于典型的路由功能, RabbitMQ 己经提供了一些内置的交换器来实现。针对更复杂的路由功能,可以将多个 交换器绑定在一起, 也可以通过插件机制来实现自己的交换器。
3.扩展性:
多个RabbitMQ节点可以组成一个集群,也可以根据实际业务情况动态地扩展 集群中节点。
4.高可用性
队列可以在集群中的机器上设置镜像,使得在部分节点出现问题的情况下队 列仍然可用。
5.多种协议:
RabbitMQ除了原生支持AMQP协议,还支持STOMP, MQTT等多种消息 中间件协议。
6.多语言客户端
RabbitMQ 几乎支持所有常用语言,比如 Java、 Python、 Ruby、 PHP、 C#、 JavaScript 等。
RabbitMQ下载
RabbitMQ 官网下载:https://www.rabbitmq.com/download.html
如下图所示:
选择上图的RabbitMQ版本,按提示下载最新版本即可
RabbitMQ安装
这里主要包含不同操作系统版本的安装,比如:windows和linux版本等。
Windows RabbitMQ安装教程(手把手教你5步成功)
选择自己系统的RabbitMQ版本,上面链接点击即可详细查看安装步骤。
安装成功后,打开浏览器访问:
http://localhost:15672
用默认账号:guest 密码: guest,登录即可:
RabbitMQ使用
RabbitMQ安装好后,我们就可以开始使用了,这里举一个简要的实例,如下:
一个producer发送消息,一个接收者接收消息,并在控制台打印出来,如下图:
RabbitMQ使用示例如下:
1.RabbitMQ Maven依赖:
<dependency> <groupId>com.rabbitmq</groupId> <artifactId>amqp-client</artifactId> <version>5.0.0</version> </dependency>
2.RabbitMQ 发送端实现
代码如下所示:
public class Send { //队列名称 private final static String QUEUE_NAME = "helloMQ"; public static void main(String[] argv) throws java.io.IOException, TimeoutException { /** * 创建连接连接到MabbitMQ */ ConnectionFactory factory = new ConnectionFactory(); //设置MabbitMQ所在主机ip或者主机名 factory.setHost("localhost"); //创建一个连接 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 + "'"); //关闭频道和连接 channel.close(); connection.close(); } }
主要流程就是5大流程:
1)producer生产发送消息;
2)创建一个频道(channel );
3)制定一个队列(queue);
4)往队列(queue)发送消息(message);
5)关闭频道和连接;
3.RabbitMQ 接收端实现
代码如下所示:
public class Receive{ // 队列名称 private final static String QUEUE_NAME = "helloMQ"; public static void main(String[] argv) throws Exception { // 打开连接和创建频道,与发送端一样 ConnectionFactory factory = new ConnectionFactory(); factory.setHost("localhost"); 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"); //创建消费者 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"); System.out.println(" [x] Received '" + message + "'"); } }; channel.basicConsume(QUEUE_NAME, true, consumer); } }
消费端:不断等待服务器推送消息,然后在控制台输出。
RabbitMQ架构
RabbitMQ架构,如下图所示:
RabbitMQ架构:会涉及如下模型:Producer、Consumer、Queue、Exchange、Broker、RoutingKey、BindingKey。
RabbitMQ集群
RabbitMQ本身是基于Erlang编写,Erlang语言天生具备分布式特性,因此RabbitMQ天然支持集群。
RabbitMQ 集群中节点包括内存节点(RAM)、 磁盘节点(Disk, 消息持久化), 集群中至少有一个 Disk 节点。
1.集群是保证可靠性的一种方式,采用多节点,是数据高可靠性的有效解决方案。
2.同时可以增加节点,通过水平扩展以达到增加消息吞吐量能力的目的。
RabbitMQ集群模式主要4种:主备模式,远程模式、镜像模式、多活模式,更加详细集群请查看:
RabbitMQ原理
RabbitMQ原理,如下图所示:
RabbitMQ的工作原理,主要包含从消息的生成到消息的消费的全过程,其中会涉及如下组件:Broker、Exchange、Queue等组件。
所以,要更好的理解RabbitMQ的工作原理,需要理解这些组件的作用。
1)Broker:简单来说就是消息队列服务器实体;
2)Exchange:即消息交换机,它指定消息按什么规则,路由到哪个队列;
3)Queue:也就是消息队列载体,每个消息都会被投入到一个或多个队列;
4)Binding:就是把exchange和queue按照路由规则绑定起来;
5)Routing Key:即路由关键字,exchange根据这个关键字进行消息投递;
6)VHost:vhost 可以理解为虚拟 broker ,即 mini-RabbitMQ server;
7)Producer:这个大家都比较清楚了,就是消息生产者,就是生成消息的程序;
8)Consumer:这个大家也比较清楚,就是消息消费者,就是接受消息的程序;
9)Channel:即可消息通道,可建立多个channel,每个channel代表一个会话任务;
RabbitMQ工作流程
把RabbitMQ的组件理解后,下面理解RabbitMQ的工作原理就容易了,主要就是:这些组件是怎样流转的。
RabbitMQ的工作流程:
第一步:生产者生产消息
主要就是:消息生产者(Producer),通过信道(Channel),把消息发送给交换机(Exchange)。
第二步:交换机接收消息
交换机(Exchange)接收消息,并且负责对消息进行路由,交换机根据消息的属性来把消息分发到不同的队列(Queue)上。
这里的交互机会涉及如下四种类型:
- 直接Direct;
- 扇出Fanout ;
- 主题Topic ;
- 消息头Headers;
第三步:消费消息
消费者监听RabbitMQ中的(Queue)队列中的消息,然后去消费。
备注:消息(Message)会一直留在队列里,直到被消费者(Consumer)消费。
RabbitMQ工作模式
1.简单模式
简单模式:主要就是一个producer发送消息,一个接收者接收消息。
模型如下图所示:
简单模式实现:一发一接的简单结构,一个队列中一条消息,只能被一个消费者消费。
简单模式的应用场景:手机短信、邮件单发。
2.工作队列模式
在简单模式中,一个生产者对应一个消费者,而实际生产过程中有多个消费者接收消息,这就是工作队列模式。
如下图所示:
与简单模式相比,多了一个或一些消费端,多个消费端共同消费同一个队列中的消息。
3.发布订阅模式
在订阅模式中,可以实现一条消息被多个消费者获取。
模型如下图所示:
在订阅模型中,多了一个 Exchange 角色,而且过程略有变化:
- 生产者:也就是要发送消息的程序,但是不再发送到队列中,而是发给交换机;
- 消费者:消息的接收者,会一直等待消息到来;
- 消息队列:接收消息、缓存消息;
交换机只负责转发消息,不具备存储消息的能力,没有队列绑定交换机,或者没有路由规则的队列,消息将丢失。
发布订阅应用场景:聊天室、上下游解耦、微信订阅号等。
4.路由模式
路由(Routing)模式是在发布订阅模式基础上的变种,发布订阅模式是无条件将所有消息分发给所有消费者队列。
如下图所示:
流程如下:
- 生产端发送的消息携带具体的路由key值;
- 交换机接收路由值;
- 交换机判断和当前交换机绑定后端队列,哪个满足路由的匹配将消息发送给这个队列;
- 根据定义的路由规则决定消息往哪个队列发送;
5.主题通配符模式
主题模式:是在原有的 Routing Key 增加了通配符,可以进行 Routing Key 的模糊匹配,进行更加灵活的消息分发。
模型如下图所示:
与路由模式类似,不同的是在主题模式中,队列绑定交换机使用的路由名字不再是具体的字符串,而是使用替代符号 ‘ * ‘或’ # ‘。
RabbitMQ应用场景
1.解耦
用了消息队列后,只要保证消息格式不变,消息的发送方和接收方并不需要彼此联系,也不需要受对方的影响,即解耦。
2.异步
异步就是将比较耗时而且不需要即时(同步)返回结果的操作,通过消息队列来实现异步化。
3.削峰
并发量大的时候,所有的请求直接怼到数据库,造成数据库连接异常。
陈睿mikechen
10年+大厂架构经验,资深技术专家,就职于阿里巴巴、淘宝、百度等一线互联网大厂。
关注「mikechen」公众号,获取更多技术干货!
后台回复【面试】即可获取《史上最全阿里Java面试题总结》,后台回复【架构】,即可获取《阿里架构师进阶专题全部合集》