1.MQ相关概念
1.1 什么是MQ
MQ(message queue),从字面意思上看,本质是个队列,FIFO 先入先出,只不过队列中存放的内容是message 而已,还是一种跨进程的通信机制,用于上下游传递消息
1.2 为什么使用MQ
流量削峰:处理能力有限,如果只能处理1W请求,1W的之内都能即时响应,现在由于活动2W用户请求,不能放弃掉1W用户,所以消息可以到消息队列,只不过处理用户下单的时间比之前长
应用解耦
异步处理
有些服务间调用是异步的:
例如 A 调用 B,B 需要花费很长时间执行,但是 A 需要知道 B 什么时候可以执行完,以前一般有两种方式:
1. A 过一段时间去调用 B 的查询 api 查询
2. A 提供一个 callback api,B 执行完之后调用 api 通知 A 服务
这两种方式都不是很优雅,使用消息总线,可以很方便解决这个问题:
1. A 调用 B 服务后,只需要监听 B 处理完成的消息
2. 当 B 处理完成后,会发送一条消息给 MQ,MQ 会将此消息转发给 A 服务
1.3 MQ的选择
大型项目:RocketMQ
日志收集(就是跟大数据量打交道):kafka
小/中型项目:RabbitMQ
社区活跃度:RabbitMQ > RocketMQ > kafka
消息持久化:RabbitMQ、RocketMQ、kafka都支持持久化
高并发:kafka = RocketMQ > RabbitMQ
吞吐量:kafka = RocketMQ > RabbitMQ
2. RabbitMq
RabbitMQ是实现了高级消息队列协议(AMQP)的开源消息代理软件(亦称面向消息的中间件)
2.1 前置概念
2.1.1 AMQP核心概念
虚拟主机(virtual host)或(vhost):
一组交换机、队列和绑定器被称为 虚拟主机(vhost)
RabbitMQ server 可以说就是一个消息队列服务器实体(Broker)
Broker当中可以有多个用户,而用户只能在虚拟主机的粒度进行权限控制,所以RabbitMQ中需要多个虚拟主机
每一个RabbitMQ服务器都有一个默认的虚拟主机
1. 交换机(exchange)
它指定消息按什么规则,路由到哪个队列。它可以被理解成具有路由表的路由程序。(发送消息的实体)
交换机可以存在多个,每个交换机在自己独立的进程当中执行,因此增加多个交换机就是增加多个进程,可以充分利用服务器上的CPU核以便达到更高的效率。
Exchange的类型
Direct:直接交换机通过消息上的路由键直接对消息进行分发,相当于精确匹配,一对一
Topic:这个交换机会将路由键和绑定上的模式进行通配符匹配,相当于模糊匹配,一对多
Fanout:交换机会将消息发送到所有和它进行绑定的队列上,广播,群发
Headers:消息头交换机使用消息头的属性进行消息路由,相当于模糊匹配(like header%),一对多
2. 队列(queue)
队列是消息载体,每个消息都会被投入到一个或多个队列
试图创建一个已经存在的队列,RabbitMQ会直接忽略这个请求(接收消息的实体)
3. 绑定器(bind)
作用:把exchange和queue按照路由规则绑定起来
将交换器和队列连接起来,并且封装消息的路由信息
2.1.2 程序中连接与消息使用的两个关键概念
1. 连接(Connection)
与RabbitMQ Server建立的一个连接
由ConnectionFactory创建
每个connection只与一个物理的Server进行连接,此连接是基于Socket进行连接的
AMQP一般使用TCP
2. 通道 (Channel)
消息通道(主要进行相关定义,发送消息,获取消息,事务处理等)
在客户端的每个连接里,可建立多个channel,每个channel代表一个会话任务
2.2 七种工作模式
简单模式:一个生产者,一个消费者
work模式:一个生产者,多个消费者,每个消费者获取到的消息唯一
订阅模式:一个生产者发送的消息会被多个消费者获取
路由模式: 发送消息到交换机并且要指定路由key ,消费者将队列绑定到交换机时需要指定路由key
topic模式:将路由键和某模式进行匹配,此时队列需要绑定在一个模式上,“#”匹配一个词或多个词,“*”只匹配一个词
RPC模式:使用RabbitMQ构建RPC系统:客户端和可伸缩RPC服务器
发布确认:与发布者进行可靠的发布确认
2.3 安装
# 1.拉取镜像
[root@izbp1j6sv2mtxgnuthuw6bz ~]# docker pull rabbitmq:3.8-management
# 2.查看镜像
[root@izbp1j6sv2mtxgnuthuw6bz ~]# docker images
# 3.启动
[root@izbp1j6sv2mtxgnuthuw6bz ~]# docker run -itd --rm --name rabbitmq -p 5672:5672 -p 15672:15672 rabbitmq:3.8-management
a5ca877169d4eda31a9c404f94565c118f1cc64de2cbb398ff17a66e72c682cd
# 4.查看启动情况
[root@izbp1j6sv2mtxgnuthuw6bz ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
a5ca877169d4 rabbitmq:3.8-management "docker-entrypoint.s…" 4 seconds ago Up 3 seconds 4369/tcp, 5671/tcp, 0.0.0.0:5672->5672/tcp, 15671/tcp, 15691-15692/tcp, 25672/tcp, 0.0.0.0:15672->15672/tcp rabbitmq
安装过程可能会遇到的问题
-
防火墙问题
-
启动web管理界面
# 进入rabbitmq
[root@izbp1j6sv2mtxgnuthuw6bz ~]# docker exec -it rabbitmq bash
# 启动web管理界面
root@a5ca877169d4:/# rabbitmq-plugins enable rabbitmq_management
2.3.1 添加新用户
# 创建账号
root@a5ca877169d4:/# rabbitmqctl add_user admin admin
Adding user "admin" ...
Done. Don't forget to grant the user permissions to some virtual hosts! See 'rabbitmqctl help set_permissions' to learn more.
# 设置用户角色
root@a5ca877169d4:/# rabbitmqctl set_user_tags admin administrator
Setting tags for user "admin" to [administrator] ...
# 设置用户权限
# set_permissions [-p <vhostpath>] <user> <conf> <write> <read>
# 用户 admin 具有/vhost1 这个 virtual host 中所有资源的配置、写、读权限
root@a5ca877169d4:/# rabbitmqctl set_permissions -p "/" admin ".*" ".*" ".*"
Setting permissions for user "admin" in vhost "/" ...
# 查看当前用户和角色
root@a5ca877169d4:/# rabbitmqctl list_users
Listing users ...
user tags
admin [administrator]
guest [administrator]