目录
目前主流的几大消息队列有:RabbitMQ、ActiveMQ、RocketMQ、Kafka、ZeroMQ 等,也有一些小众的比如Beanstalk
- RabbitMQ :在吞吐量方面虽然稍逊于Kafka和RocketMQ ,但是由于它基于erlang开发,所以并发能力很强,性能极其好,延时很低,达到微秒级
- 如果业务场景对并发量要求不是太高(十万级、百万级),那这四种消息队列中,RabbitMQ一定是你的首选
- ActiveMQ:基于JAVA语言开发,其社区算是比较成熟,但是目前来说,ActiveMQ的性能比较差,而且版本迭代很慢,不推荐使用
- RocketMQ :阿里出品,Java系开源项目,源代码我们可以直接阅读,然后可以定制自己公司的MQ,并且RocketMQ有阿里巴巴的实际业务场景的实战考验
- 接口这块不是按照标准JMS规范走的有些系统要迁移需要修改大量代码。还有就是阿里出台的技术,你得做好这个技术万一被抛弃,社区黄掉的风险,那如果你们公司有技术实力我觉得用RocketMQ挺好的
- Kafka :由Scala和Java编写,其特点其实很明显,就是仅仅提供较少的核心功能,但是提供超高的吞吐量,ms级的延迟,极高的可用性以及可靠性,而且分布式可以任意扩展
- Kafka唯一的一点劣势是有可能消息重复消费,那么对数据准确性会造成极其轻微的影响,在大数据领域中以及日志采集中,这点轻微影响可以忽略这个特性天然适合大数据实时计算以及日志收集
- ZeroMQ:只是一个网络编程的Pattern库,将常见的网络请求形式(分组管理,链接管理,发布订阅等)模式化、组件化,简而言之socket之上、MQ之下
|----------|-----------------------------------------------------------------------------------------------------|
| 角色 | 名词 |
| Broker | Kafka集群包含一个或多个服务器,每个服务器被称为broker(经纪人) * 消息服务器,作为server提供消息核心服务 |
| Topic | 每条发布到Kafka集群的消息都有一个分类,这个类别被称为Topic(主题) * 主题,发布订阅模式下的消息统一汇集地,不同生产者向topic发送消息,由MQ服务器分发到不同的订阅者,实现消息的广播 |
| Producer | 指消息的生产者,负责发布消息到kafka broker * 消息生产者,业务的发起方,负责生产消息传输给broker |
| Consumer | 指消息的消费者,从kafka broker拉取数据,并消费这些已发布的消息 * 消息消费者,业务的处理方,负责从broker获取消息并进行业务逻辑处理 |
| Queue | * 队列,PTP模式下,特定生产者向特定queue发送消息,消费者订阅特定的queue完成指定消息的接收 |
| Message | 消息,通信的基本单位,每个producer可以向一个topic发布一些消息 * 消息体,根据不同通信协议定义的固定格式进行编码的数据包,来封装业务数据,实现消息的传输 |
消息队列的两种工作模式及缺点
- Point-to-Point
- 其实就是点对点,其过程理解起来比较简单(它好比是两个人打电话,这两个人是独享这一条通信链路的。一方发送消息,另外一方接收)在点对点模式下,消息被保留在队列中。 一个或多个消费者可以消耗队列中的消息,但是特定消息只能由最多一个消费者消费。 一旦消费者读取队列中的消息,它就从该队列中消失
- Pub/Sub
- 即发布/订阅模式,该模式有点类似于我们日常生活中订阅报纸。对于每一个订阅者来说,可以选择一份或者多份报纸,那么这些我们订阅的报纸,就相当于发布订阅模式里的topic。有很多个人订阅报纸,也有人可能和我订阅了相同的报纸。多人订阅了相同的报纸相当于多人在同一个topic里注册了对于一份报纸发行方来说,它和所有的订阅者就构成了一个1对多的关系。在这种模式下,消息被保留在主题中
- 缺点:
- 系统可用性降低:毕竟在整个架构中,我们单独加了一个消息队列中间件,所以增加了风险,如果消息队列服务挂掉,势必会影响到整个架构
- 系统复杂性提高:本来非常简单的一个逻辑设计,但偏偏要在中间插入一个消息队列,所以这增加了程序员的工作量,需要考虑如何保证消息没有被重复消费、消息有没有丢失、消息顺序等细节问题
- 数据一致性无法保证:消息如果没有正确写入到消息队列里,或者说读取消息的服务并没有正确读取到消息,这都会影响到数据的一致性
|------|----------------------------------------------------------------------------------------------------------|
| RabbitMQ术语 ||
| 生产者 | 产生消息的进程或服务 |
| 消费者 | 接收消息的进程或服务 |
| 队列 | RabbitMQ是消息队列中间件,而真正储存消息数据的就是队列,队列可以有很多 |
| 交换器 | 类似于网络设备交换机,它可以根据不同的关键字,将消息发送到不同的队列 |
| 虚拟主机 | 虚拟主机提供了资源的逻辑分组和分隔,每一个虚拟主机本质上是mini版的RabbitMQ服务器,他们有用自己的连接、队列、绑定、交换器,更重要的是有用自己的权限机制,这有点类似服务器和运行在服务器上的虚拟机一样 |
一、CentOS7下安装RabbitMQ(单机)
1:安装erlang
//先用阿里云的仓库
rm -rf /etc/yum.repos.d/*
curl -o /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos-7.repo
curl -o /etc/yum.repos.d/epel.repo https://mirrors.aliyun.com/repo/epel-7.repo
yum clean all
[root@localhost ~]# yum -y install erlang
2:安装RabbitMQ
[root@localhost ~]# yum -y install rabbitmq-server
3:启动RabbitMQ
[root@localhost ~]# systemctl start rabbitmq-server ## 监听端口为4369,25672
[root@localhost ~]# ps aux |grep rabbit ## 查看rabbit进程
[root@localhost ~]# netstat -lntp ## 查看监听端口
4:开启web管理控制台
[root@localhost ~]# rabbitmq-plugins enable rabbitmq_management ##激活插件
[root@localhost ~]# rabbitmq-plugins list ## 查看所有插件
[root@localhost ~]# systemctl restart rabbitmq-server
此时可以通过 http://ip:15672 来访问rabbitmq的web管理控制台,用户名密码都是guest,但是有个限制,只允许127.0.0.1访问,
所以还需在本机配置一个nginx代理
5:Nginx代理
[root@localhost ~]# yum install -y epel-release ##安装可扩展源
[root@localhost ~]# yum install -y nginx ##安装nginx
vi /etc/nginx/conf.d/rabbitmq.conf ##内容如下
server {
listen 80;
server_name www.fllrabbit.com; #域名自定义,如果没有dns解析,只能绑定hosts
location /
{
proxy_pass http://127.0.0.1:15672;
proxy_set_header Host $host; ##指定主机名,$host就是server_name
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
##后两行为了在访问日志中显示真正客户端的ip,而不是代理的ip
}
}
[root@localhost ~]# systemctl start nginx ##启动或重启nginx服务
现在可以通过宿主机绑定hosts,然后通过浏览器访问rabbit,账号密码都是:guest
二、rabbitmq常用命令
1:虚拟机管理
[root@localhost ~]# rabbitmqctl list_vhosts ##列出所有的虚拟主机
[root@localhost ~]# rabbitmqctl add_vhost fll ##创建名字叫fll的虚拟主机
[root@localhost ~]# rabbitmqctl delete_vhost fll ##删除名字叫fll的虚拟主机
rabbitmqctl add_vhost <虚拟主机名字> #创建虚拟主机
rabbitmqctl delete_vhost <虚拟主机名字> #删除虚拟主机
2:用户管理
[root@localhost ~]# rabbitmqctl add_user user1 user1_passwd
##创建user1用户,密码为user1_passwd
[root@localhost ~]# rabbitmqctl list_users ##列出所有用户
[root@localhost ~]# rabbitmqctl change_password user1 new_passwd ##更改user1的密码为new_passwd
[root@localhost ~]# rabbitmqctl delete_user user1 #删除user1用户
rabbitmqctl list_users #列出用户
rabbitmqctl add_user <username> <password> #创建用户
rabbitmqctl change_password <username> <password> ##更改用户密码
rabbitmqctl delete_user <username> #删除用户
rabbitmqctl clear_password <username> #清除用户密码
3:tags角色介绍
[root@localhost ~]# rabbitmqctl set_user_tags user1 managemnet
##赋予user1用户management角色
[root@localhost ~]# rabbitmqctl set_user_tags user2 monitoring management
##同时赋予多个角色
[root@localhost ~]# rabbitmqctl set_permissions -p fll user1 '.*' '.*' '.*'
##针对fll虚拟主机给user1用户设置所有的配置、读写queue和exchange的权限。默认是没有任何权限的
rabbitmqctl set_user_tags <username> <rolename> #赋予用户某个角色
rabbitmqctl set_permissions -p <vhostname> <username> <conf> <write> <read>
#给用户设置权限
[root@localhost ~]# rabbitmqctl list_user_permissions user1 ##列出user1的权限
[root@localhost ~]# rabbitmqctl list_permissions -p fll ##列出fll下的所有用户权限
[root@localhost ~]# rabbitmqctl clear_permissions -p fll user2
##清除user2在fll上的权限
rabbitmqctl list_user_permissions <username>
#列出某用户的权限,即该用户对哪个虚拟主机有权限
rabbitmqctl list_permissions -p <vhostname>
#列出指定虚拟主机下所有用户的权限,即哪些用户对该虚拟主机有权限
rabbitmqctl clear_permissions -p <vhostname> <user>
#清除某用户在指定虚拟机上的授权
- (1) 超级管理员(administrator):guest
- 可登陆管理控制台(启用management plugin的情况下),可查看所有的信息,并且可以对用户,策略(policy)进行操作。
- (2) 监控者(monitoring)
- 可登陆管理控制台(启用management plugin的情况下),同时可以查看rabbitmq节点的相关信息(进程数,内存使用情况,磁盘使用情况等)
- (3) 策略制定者(policymaker)
- 可登陆管理控制台(启用management plugin的情况下), 同时可以对policy进行管理。但无法查看节点的相关信息。
- (4) 普通管理者(management)
- 仅可登陆管理控制台(启用management plugin的情况下),无法看到节点信息,也无法对策略进行管理。
- (5) 其他
- 无法登陆管理控制台,通常就是普通的生产者和消费者
4:插件管理
rabbitmq-plugins list ##获取RabbitMQ插件列表
rabbitmq-plugins enable <插件名字> ##安装RabbitMQ插件
rabbitmq-plugins disable <插件名字> ##卸载某个插件
5:限制
rabbitmqctl set_vhost_limits -p vhost_name '{"max-connections": 256}'
#设置虚拟主机的最大连接数
rabbitmqctl set_vhost_limits -p vhost_name '{"max-connections": 0}'
#不允许客户端连接虚拟主机
rabbitmqctl set_vhost_limits -p vhost_name '{"max-connections": -1}'
#不限制连接数
rabbitmqctl set_vhost_limits -p vhost_name '{"max-queues": 1024}'
#限制虚拟主机里最大的队列数
rabbitmqctl set_vhost_limits -p vhost_name '{"max-queues": -1}'
#不限制队列数
6:其他
rabbitmqctl list_exchanges
#列出所有的交换器
rabbitmqctl list_bindings
#列出所有的绑定,即把exchange和queue按照路由规则绑定起来
rabbitmqctl list_queues
#分别查看当前系统种存在的Exchange和Exchange上绑定的Queue信息。
rabbitmqctl status
#查看运行信息
三、RabbitMQ集群
- RabbitMQ本身是基于Erlang编写的,Erlang天生支持分布式(通过同步Erlang集群各节点的cookie来实现),因此不需要像Kafka那样通过ZooKeeper来实现分布式集群
- 元数据
- RabbitMQ内部有各种基础构件,包括队列、交换器、绑定、虚拟主机等,他们组成了AMQP协议消息通信的基础,而这些构件以元数据的形式存在
- 内存节点与磁盘节点
- 在集群中的每个节点,要么是内存节点,要么是磁盘节点,如果是内存节点,会将所有的元数据信息仅存储到内存中,而磁盘节点则不仅会将所有元数据存储到内存上, 还会将其持久化到磁盘。所以在搭建集群的时候,为了保证数据的安全性和性能,最好是两种节点都要有
- 元数据
|----------|----------------|------|
| 主机名 | Ip | 节点类型 |
| centos01 | 192.168.10.101 | 磁盘节点 |
| Centos02 | 192.168.10.102 | 内存节点 |
| Centos03 | 192.168.10.103 | 内存节点 |
部署集群
(1)配置hosts以及hostname
三台机器设置hostname
hostnamectl set-hostname centos01
hostnamectl set-hostname centos02
hostnamectl set-hostname centos03
三台机器上都需要编辑如下hosts
192.168.10.101 centos01
192.168.10.102 centos02
192.168.10.103 centos03
(2)关闭selinux以及firewalld
三台机器都要执行
setenforce 0
systemctl stop firewalld
systemctl disable firewalld //设置永久关闭
(3)安装rabbitmq(三台机器都要安装)
//先用阿里云的仓库
rm -rf /etc/yum.repos.d/*
curl -o /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos-7.repo
curl -o /etc/yum.repos.d/epel.repo https://mirrors.aliyun.com/repo/epel-7.repo
yum clean all
[root@centos01 ~]# yum -y install erlang
...
[root@centos01 ~]# yum -y install rabbitmq-server
(4)启动服务
三台机器都启动起来
systemctl start rabbitmq-server
systemctl enable rabbitmq-server //可以永久开启rabbitmq服务
ps aux | grep rabbit //用ps命令查询rabbit进程
(5)安装management插件,重启服务
三台机器都要开启
rabbitmq-plugins enable rabbitmq_management
systemctl restart rabbitmq-server
(6)同步cookie文件
//确保集群节点能够相互认证,如果.erlang.cookie文件不一致,节点间将无法建立信任关系,从而无法正常加入集群
cat /var/lib/rabbitmq/.erlang.cookie
在centos01上操作(其实任何一个上都可以)
scp /var/lib/rabbitmq/.erlang.cookie root@centos02:/var/lib/rabbitmq/
scp /var/lib/rabbitmq/.erlang.cookie root@centos03:/var/lib/rabbitmq/
[root@centos01 ~]# reboot //重启三台主机,然后检查三台主机的RabbitMQ服务,正常情况下是都在运行的
[root@centos01 ~]# ps aux | grep rabbit
(7)分配节点
centos01为磁盘节点,centos02和centos03为内存节点
centos02和centos03上都执行:
停止rabbitmq
systemctl start rabbitmq-server
rabbitmqctl stop_app
将centos02、03作为内存节点连接到centos01
rabbitmqctl join_cluster --ram rabbit@centos01
开启rabbitmq
rabbitmqctl start_app
查看集群状态
rabbitmqctl cluster_status
Cluster status of node rabbit@mq02 ...
[{nodes,[{disc,[rabbit@mq01]},{ram,[rabbit@mq03,rabbit@mq02]}]},
{running_nodes,[rabbit@mq03,rabbit@mq01,rabbit@mq02]},
{cluster_name,<<"rabbit@mq02">>},
{partitions,[]}]
...done.
// disc:表示磁盘节点
// ram:表示内存节点