消息队列之RabbitMQ

Posted yt丶独自

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了消息队列之RabbitMQ相关的知识,希望对你有一定的参考价值。

一、RabbitMQ

官方网址: https://www.rabbitmq.com/

 

1.1 RabbitMQ 简介:

RabbitMQ 采用 Erlang 语言开发,Erlang 语言由 Ericson 设计,Erlang 在分布式编程和故障恢复方面表现出色,电信领域被广泛使用。

Erlang语言官方网址:https://www.erlang.org/

 

 

Broker: 接收和分发消息的应用,RabbitMQ Server 就是 Message Broker。

Virtual host:出于多租户和安全因素设计的,把 AMQP 的基本组件划分到一个虚拟的分组中,类似于网络中的 namespace 概念,当多个不同的用户使用同一个RabbitMQ server 提供的服务时,可以划分出多个 vhost,每个用户在自己的 vhost创建 exchange/queue 等。

Connection:publisher/consumer 和 broker 之间的 TCP 连接。

Channel:如果每一次访问 RabbitMQ 都建立一个 Connection,在消息量大的时候建立 TCP Connection 的开销将是巨大的,效率也较低。Channel 是在 connection内部建立的逻辑连接,如果应用程序支持多线程,通常每个 thread 创建单独的channel 进行通讯,AMQP method 包含了 channel id 帮助客户端和 message broker识别 channel,所以 channel 之间是完全隔离的。Channel 作为轻量级的 Connection极大减少了操作系统建立 TCP connection 的开销。

Exchange:message 到达 broker 的第一站,根据分发规则,匹配查询表中的 routing key,分发消息到 queue 中去。常用的类型有:direct (point-to-point),topic (publish-subscribe) and fanout (multicast)。

Queue:消息最终被送到这里等待 consumer 取走。

Binding:exchange 和 queue 之间的虚拟连接,binding 中可以包含 routing key。Binding 信息被保存到 exchange 中的查询表中,用于 message 的分发依据。

RabbitMQ的优势:

1、基于 erlang 语言开发,具有高并发优点、支持分布式;

2、具有消息确认机制、消息持久化机制,消息可靠性和集群可靠性高;

3、简单易用、运行稳定、跨平台、多语言;

4、开源。

Queue 的特性:

1、消息基于先进先出的原则进行顺序消费;

2、消息可以持久化到磁盘节点服务器;

3、消息可以缓存到内存节点服务器提高性能。

1.2 RabbitMQ中的生产者消费者示例:

 

 

生产者发送消息到 broker server(RabbitMQ),在 Broker 内部,用户创建

Exchange/Queue,通过 Binding 规则将两者联系在一起,Exchange 分发消息,根据类型/binding 的不同分发策略有区别,消息最后来到 Queue 中,等待消费者取走。

JMS 是在 2001 年发布的 Java 消息服务(Java Message Service)应用程序接口,是一个 Java 平台中关于面向消息中间件(MOM,message oriented middleware)的 API,用于在两个应用程序之间,或分布式系统中发送消息,进行异步通信。

1.3 RabbitMQ单机部署:

官网下载地址:

https://www.rabbitmq.com/download.html

github下载地址:

https://github.com/rabbitmq/rabbitmq-server/releases

1.3.1 ubuntu1804部署单机版RabbitMQ

官方参考: https://www.rabbitmq.com/install-debian.html

1.3.1.1 主机名解析:在当前MQ服务器配置本地主机名解析

#编辑hosts文件,添加本地主机名解析
root@ubuntu1804-40:~# vim /etc/hosts
10.0.0.40 ubuntu1804-40
#测试是否添加成功
root@ubuntu1804-40:~# ping ubuntu1804-40
PING ubuntu1804-40 (10.0.0.40) 56(84) bytes of data.
64 bytes from ubuntu1804-40 (10.0.0.40): icmp_seq=1 ttl=64 time=0.033 ms
64 bytes from ubuntu1804-40 (10.0.0.40): icmp_seq=2 ttl=64 time=0.030 ms

1.3.1.2 服务器安装RabbitMQ

#安装基础命令及添加key
sudo apt-get -y install curl gnup
curl -1sLf \'https://packagecloud.io/rabbitmq/rabbitmq-server/gpgkey\' | sudo apt-key add -

#安装apt HTTPS传输
sudo apt-get -y install apt-transport-https

#添加apt源
sudo tee /etc/apt/sources.list.d/rabbitmq.list <<EOF
deb http://ppa.launchpad.net/rabbitmq/rabbitmq-erlang/ubuntu bionic main
deb-src http://ppa.launchpad.net/rabbitmq/rabbitmq-erlang/ubuntu bionic main
deb https://packagecloud.io/rabbitmq/rabbitmq-server/ubuntu/ bionic main
deb-src https://packagecloud.io/rabbitmq/rabbitmq-server/ubuntu/ bionic main
EOF

#更新apt源
sudo apt update

#查看可安装的RabbitMQ版本
sudo apt-cache madison rabbitmq-server

#安装erlang
sudo apt-get install -y erlang-base \\
                        erlang-asn1 erlang-crypto erlang-eldap erlang-ftp erlang-inets \\
                        erlang-mnesia erlang-os-mon erlang-parsetools erlang-public-key \\
                        erlang-runtime-tools erlang-snmp erlang-ssl \\
                        erlang-syntax-tools erlang-tftp erlang-tools erlang-xmerl

#安装RabbitMQ
sudo apt-get install rabbitmq-server -y --fix-missing

1.3.1.3 启动RabbitMQ

#启动RabbitMQ,ubuntu安装完成后自动启动
systemctl start rabbitmq-server.service

#停止RabbitMQ
systemctl stop rabbitmq-server.service

#查看RabbitMQ状态
systemctl status rabbitmq-server.service

1.3.1.4 RabbitMQ常用命令

#查看节点状态
rabbitmqctl status

#查看所有可用插件
rabbitmq-plugins list
#启用插件
rabbitmq-plugins enable <plugin-name>
#停用插件
rabbitmq-plugins disable <plugin-name>

 

 

#列出所有用户
rabbitmqctl list_users
#添加用户
rabbitmqctl add_user <username> <password>
#删除用户
rabbitmqctl delete_user <username>
#清除用户权限
rabbitmqctl clear_permissions -p vhostpath <username>
#列出用户权限
rabbitmqctl list_user_permissions <username>
#设置用户权限
rabbitmqctl set_permissions -p vhostpath <username> ".*" ".*" ".*"
#修改用户密码
rabbitmqctl change_password <username> <newpassword>

1.3.1.5 RabbitMQ插件管理

官方参考:https://www.rabbitmq.com/management.html

#开启web界面管理插件
 rabbitmq-plugins enable rabbitmq_management

5672:消费者访问端口

15672:web管理端口

25672:集群状态通信端口

1.3.1.6 登录web管理界面

登录地址:服务器ip:15672

RabbitMQ从3.3.0开始禁止使用guest/guest权限通过除了localhost外的访问,直接访问会报以下错误:

 

 登录web界面方法:

#由于我的RabbitMQ版本是3.8.16,没有rabbit.app文件,只能重新添加用户并授权
#添加用户
rabbitmqctl add_user <username> <password>
#设置添加的用户为管理员
rabbitmqctl set_user_tags <username> administrator
#赋予权限
rabbitmqctl set_permissions -p / <username> ".*" ".*" ".*"
#重启服务
systemctl restart rabbitmq-server.service

1.4 RabbitMQ集群部署

Rabbitmq 集群分为二种方式:

普通模式:创建好 RabbitMQ 集群之后的默认模式。

镜像模式:把需要的队列做成镜像队列。

普通集群模式:

queue 创建之后,如果没有其它 policy,消息实体只存在于其中 一个节点,A、B 两个 Rabbitmq 节点仅有相同的元数据,即队列结构,但队列的数据仅保存有一份,即创建该队列的 rabbitmq 节点(A 节点),当消息进入 A 节 点的 Queue 中后,consumer 从 B 节点拉取时,RabbitMQ 会临时在 A、B 间进行消息传输,把 A 中的消息实体取出并经过 B 发送给 consumer,所以 consumer 可以连接每一个节点,从中取消息,该模式存在一个问题就是当 A 节点故障后,B 节点无法取到 A 节点中还未消费的消息实体。

镜像集群模式:

把需要的队列做成镜像队列,存在于多个节点,属于 RabbitMQ 的 HA 方案(镜 像模式是在普通模式的基础上,增加一些镜像策略) 该模式解决了普通模式中的数据丢失问题,其实质和普通模式不同之处在于,消 息实体会主动在镜像节点间同步,而不是在 consumer 取数据时临时拉取,该模 式带来的副作用也很明显,除了降低系统性能外,如果镜像队列数量过多,加之 大量的消息进入,集群内部的网络带宽将会被这种同步通讯大大消耗掉,所以在对可靠性要求较高的场合中适用,一个队列想做成镜像队列,需要先设置 policy, 然后客户端创建队列的时候,rabbitmq 集群根据“队列名称”自动设置是普通集群模式或镜像队列。

集群种有两种节点类型:

内存节点:只将数据保存到内存。

磁盘节点:保存数据到内存和磁盘。

内存节点虽然不写入磁盘,但是它执行比磁盘节点要好,集群中,只需要一个 磁盘节点来保存数据就足够了如果集群中只有内存节点,那么不能全部停止它 们,否则所有数据消息在服务器全部停机之后都会丢失。

在一个 rabbitmq 集群里,有 3 台或以上机器,其中 1 台使用磁盘模式,其它节 点使用内存模式,内存节点无访问速度更快,由于磁盘 IO 相对较慢,因此可作为数据备份使用。

1.4.1 debian10部署RabbitMQ集群

环境配置:10.0.0.10,10.0.0.20,10.0.0.30

1.4.1.1 主机名解析配置

各 RabbitMQ 服务器配置本地主机名解析:

10.0.0.10 debian10-10
10.0.0.20 debian10-20
10.0.0.30 debian10-30

1.4.1.2 各服务器安装RabbitMQ

#安装基础命令依赖及添加key
sudo apt-get install curl gnupg debian-keyring debian-archive-keyring apt-transport-https -y
sudo apt-key adv --keyserver "hkps://keys.openpgp.org" --recv-keys "0x0A9AF2115F4687BD29803A206B73A36E6026DFCA"
sudo apt-key adv --keyserver "keyserver.ubuntu.com" --recv-keys "F77F1EDA57EBB1CC"
curl -1sLf \'https://packagecloud.io/rabbitmq/rabbitmq-server/gpgkey\' | sudo apt-key add -

#添加apt源
sudo tee /etc/apt/sources.list.d/rabbitmq.list <<EOF
deb https://dl.cloudsmith.io/public/rabbitmq/rabbitmq-erlang/deb/debian buster main
deb-src https://dl.cloudsmith.io/public/rabbitmq/rabbitmq-erlang/deb/debian buster main
deb https://dl.cloudsmith.io/public/rabbitmq/rabbitmq-server/deb/debian buster main
deb-src https://dl.cloudsmith.io/public/rabbitmq/rabbitmq-server/deb/debian buster main
EOF

#更新apt源
sudo apt update

#查看可安装的RabbitMQ版本
sudo apt-cache madison rabbitmq-server

#安装erlang
sudo apt-get install -y erlang-base \\
                        erlang-asn1 erlang-crypto erlang-eldap erlang-ftp erlang-inets \\
                        erlang-mnesia erlang-os-mon erlang-parsetools erlang-public-key \\
                        erlang-runtime-tools erlang-snmp erlang-ssl \\
                        erlang-syntax-tools erlang-tftp erlang-tools erlang-xmerl

#安装RabbitMQ
sudo apt-get install rabbitmq-server -y --fix-missing

1.4.1.3 创建RabbitMQ集群

Rabbitmq 的集群是依赖于 erlang 的集群来工作的,所以必须先构建起 erlang 的 集群环境,而 Erlang 的集群中各节点是通过一个 magic cookie 来实现的,这个 cookie 存放在 /var/lib/rabbitmq/.erlang.cookie 中,文件是 400 的权限,所以必须 保证各节点 cookie 保持一致,否则节点之间就无法通信。

debian10的ssh默认不能使用密码登录,如需使用scp,则需要修改/etc/ssh/sshd_config文件
需要将PermitRootLogin no / without-password 改为 PermitRootLogin yes
重启ssh服务:systemctl restart sshd

拷贝前需要停止RabbitMQ服务。

systemctl stop rabbitmq-server.service

将节点1上的erlang.cookie文件拷贝到节点2和节点3服务器。

scp /var/lib/rabbitmq/.erlang.cookie 10.0.0.20:/var/lib/rabbitmq/.erlang.cookie
scp /var/lib/rabbitmq/.erlang.cookie 10.0.0.30:/var/lib/rabbitmq/.erlang.cookie

查看节点1的集群名称,并将其余2个节点加入到集群

#查看节点1的集群名称
root@debian10-10:/# rabbitmqctl cluster_status
Cluster status of node rabbit@debian10-10 ...
#加入集群,以内存节点的模式
root@debian10-20:~# rabbitmqctl join_cluster rabbit@debian10-10 --ram
root@debian10-30:~# rabbitmqctl join_cluster rabbit@debian10-10 --ram
#再次查看节点状态
#3.7X版本
root@debian10-10:/# rabbitmqctl cluster_status
Cluster status of node rabbit@debian10-10 ...
[{nodes,[{disc,[\'rabbit@debian10-10\']},
         {ram,[\'rabbit@debian10-30\',\'rabbit@debian10-20\']}]},
 {running_nodes,[\'rabbit@debian10-30\',\'rabbit@debian10-20\',
                 \'rabbit@debian10-10\']},
 {cluster_name,<<"rabbit@debian10-10">>},
 {partitions,[]},
 {alarms,[{\'rabbit@debian10-30\',[]},
          {\'rabbit@debian10-20\',[]},
          {\'rabbit@debian10-10\',[]}]}]

#3.8.X版本
 rabbitmqctl cluster_status 
Cluster status of node rabbit@mq-server2 ...
Basics
Cluster name: rabbit@mq-server2
Disk Nodes
rabbit@mq-server2
Running Nodes
rabbit@mq-server2
Versions
rabbit@mq-server2: RabbitMQ 3.8.3 on Erlang 22.3

要在web界面上看到3个节点正常,需要每个节点都开启web界面。

#开启RabbitMQ的web界面
rabbitmq-plugins enable rabbitmq_management

 

以上是关于消息队列之RabbitMQ的主要内容,如果未能解决你的问题,请参考以下文章

微服务专题之.Net6下集成消息队列-RabbitMQ交换机模式代码演示(全)

rabbitmq - 不会获取队列中的所有消息

【rabbitMQ】消息队列之 rabbitMQ

快速入门分布式消息队列之 RabbitMQ(下)

消息队列之RabbitMQ

消息队列之 RabbitMQ