一、RabbitMQ初识
RabbitMQ是一个实现了高级消息队列协议(AMQP的消息代理(也叫消息中间件),它接受并转发消息。它可以帮你处理一些逻辑的事务,从而进行解耦,比如用户注册落库之后,还需要发送邮件验证、需要发送新人红包等等事情,就可以交给中间件去做。也可以把它当成一个邮局:当你想邮寄信件的时候,你会把信件放在投递箱中,并确信邮递员最终会将信件送到收件人的手里。在这个例子中,RabbitMQ就相当与投递箱、邮局和邮递员。
1.1 AMQP协议
AMQP,即Advanced Message Queuing Protocol,一个提供统一消息服务的应用层标准高级消息队列协议,是应用层协议的一个开放标准,为面向消息的中间件设计。基于此协议的客户端与消息中间件可传递消息,并不受客户端/中间件产品、不同的开发语言等条件的限制。
1.2 典型应用场景
跨系统的异步通信 ,异步、解耦、削峰。
应用内的同步变成异步 秒杀:自己发送给自己
基于Pub/Sub模型实现的事件驱动 ,摒弃ELT(比如全量 同步商户数据); 摒弃API(比如定时增量获取用户、获取产品,变成增量广播)。
利用RabbitMQ实现事务的最终一致性
1.3 RabbitMQ的特性
RabbitMQ使用Erlang语言编写,使用Mnesia数据库存储消息。
可靠性(Reliability) RabbitMQ 使用一些机制来保证可靠性,如持久化、传输确认、发布确认。
灵活的路由(Flexible Routing) 在消息进入队列之前,通过 Exchange 来路由消息的。对于典型的路由功能,RabbitMQ 已经提供了一些内置的 Exchange 来实现。针对更复杂的路由功能,可以将多个 Exchange 绑定在 一起,也通过插件机制实现自己的 Exchange 。
消息集群(Clustering) 多个 RabbitMQ 服务器可以组成一个集群,形成一个逻辑 Broker 。
高可用(Highly Available Queues) 队列可以在集群中的机器上进行镜像,使得在部分节点出问题的情况下
队列仍然可用。
多种协议(Multi-protocol) RabbitMQ 支持多种消息队列协议,比如 AMQP、STOMP、MQTT 等等。
多语言客户端(Many Clients) RabbitMQ 几乎支持所有常用语言,比如 Java、.NET、Ruby、PHP、C#、 JavaScript 等等。
管理界面(Management UI) RabbitMQ 提供了一个易用的用户界面,使得用户可以监控和管理消息、集群 中的节点。
插件机制(Plugin System) RabbitMQ提供了许多插件,以实现从多方面扩展,当然也可以编写自己的插件。
1.4 工作模型
Broker
我们要使用 RabbitMQ 来收发消息,必须要安装一个 RabbitMQ 的服务,可以安装在 Windows 上面也可以安装在 Linux 上面,默认是 5672 的端口。这台 RabbitMQ 的服务器我们把它叫做 Broker, MQ 服务器帮助我们做的事情就是存储、转发消息。
Connection
无论是生产者发送消息,还是消费者接收消息,都必须要跟 Broker 之间建立一个连接,这个连接是一个 TCP 的长连接。
Channel
如果所有的生产者发送消息和消费者接收消息,都直接创建和释放 TCP 长连接的话,对于 Broker 来说肯定会造成很大的性能损耗,因为 TCP 连接是非常宝贵的资源,创建和释放也要消耗时间。所以在 AMQP 里面引入了 Channel 的概念,它是一个虚拟的连接。我们把它翻译成通道,或者消息信道。这样我们就可以在保持的 TCP 长连接里面去创建和释放Channel,大大了减少了资源消耗。另外一个需要注意的是,Channel 是 RabbitMQ 原生 API 里面的最重要的编程接口,也就是说我们定义交换机、队列、绑定关系,发送消息消费消息,调用的都是 Channel 接口上的方法。
Queue
在其他一些 MQ 里面,比如ActiveMQ ,消息都是发送到队列上的。队列是真正用来存储消息的,是一个独立运行的进程,有自己的数据库。消费者获取消息有两种模式,一种是 Push 模式,只要生产者发到服务器,就马上推送给消费者。另一种是 Pull 模式,消息存放在服务端,只有消费者主动获取才能拿到消息。消费者需要写一个 while 循环不断地从队列获取消息吗?不需要,我们可以基于事件机制,实现消费者对队列的监听。
由于队列有 FIFO 的特性,只有确定前一条消息被消费者接收之后,才会把这条消息从数据库删除,继续投递下一条消息。
Exchange
在 RabbitMQ 里面永远不会出现消息直接发送到队列的情况。因为在 AMQP 里面引入了交换机(Exchange)的概念,用来实现消息的灵活路由。
交换机是一个绑定列表,用来查找匹配的绑定关系。队列使用绑定键(Binding Key)跟交换机建立绑定关系。生产者发送的消息需要携带路由键(Routing Key),交换机收到消息时会根据它保存的绑定列表,决定将消息路由到哪些与它绑定的队列上。注意:交换机与队列、队列与消费者都是多对多的关系。
Vhost
我们每个需要实现基于 RabbitMQ 的异步通信的系统,都需要在服务器上创建自己要用到的交换机、队列和它们的绑定关系。如果某个业务系统不想跟别人混用一个系统,怎么办?再采购一台硬件服务器单独安装一个 RabbitMQ 服务?这种方式成本太高了。在同一个硬件服务器上安装多个 RabbitMQ 的服务呢?比如再运行一个 5673 的端口?
没有必要,因为 RabbitMQ 提供了虚拟主机 VHOST。VHOST 除了可以提高硬件资源的利用率之外,还可以实现资源的隔离和权限的控制。它的作用类似于编程语言中的 namespace 和 package,不同的 VHOST 中可以有同名的 Exchange 和 Queue,它们是完全透明的。
这个时候,我们可以为不同的业务系统创建不同的用户(User),然后给这些用户分配 VHOST 的权限。比如给风控系统的用户分配风控系统的 VHOST 的权限,这个用户可以访问里面的交换机和队列。给超级管理员分配所有 VHOST 的权限。
Producer生产者:主要将消息投递到对应的Exchange上面。一般是独立的程序。
Consumer消费者:消息的接收者,一般是独立的程序。
1.5 三种主要的交换机
1.5.1 Direct Exchange 直连交换机
定义:直连类型的交换机与一个队列绑定时,需要指定一个明确的binding key。
路由规则:发送消息到直连类型的交换机时,只有routing key跟binding key完全匹配时,绑定的队列才能收到消息。
例如:
1.5.2 Topic Exchange 主题交换机
定义:主题类型的交换机与一个队列绑定时,可以指定按模式匹配的routing key。
通配符有两个, 代表匹配一个单词。 代表匹配零个或者多个单词。单词与单词之间用 隔开。
路由规则:发送消息到主题类型的交换机时,routing key符合binding key的模式时,绑定的队列才能收到消息。
例如:
1.5.2 Fanout Exchange 广播交换机
定义:广播类型的交换机与一个队列绑定时,不需要指定binding key。
路由规则:当消息发送到广播类型的交换机时,不需要指定routing key,所有与之绑定的队列都能收到消息。
例如:
二、安装运行
2.1 windows和linux系统
直接官网下载压缩包,解压即可,到sbin目录启动rabbitmq-server即可。
2.2 mac
mac系统下载安装包也可以,我是用homebrew安装的。
安装后会有启动命令。
启动完成访问。看到下面页面就是安装成功了。
账号密码都是guest。也不用输入。直接login就行。
三、简单的生产消费例子
先引入pom依赖。基于springboot的。
3.1 生产者
3.2 消费者
2.3 运行结果
2.4 参数说明
声明交换机的参数
声明队列的参数
消息属性 BasicProperties
主要的参数:
------------END-----------
领取专属 10元无门槛券
私享最新 技术干货