RabbitMQ-笔记
-------------------------------------------------------------------------------------------------
为什么要使用消息队列
- 异步处理
- 系统解耦
解耦是消息中间队列解决的最本质问题。所谓解耦,简单一点就是一个事务,只关心核心的流程。而需要依赖其他系统但不那么重要的事情,有通知即可,无需等待结果。换句话说,关心的是“通知,而非“处理”。
比如下单过程中,需要发送短信积分,如果下游系统过慢(比如短信网关速度不好),主流程一直在等待。用户肯定不希望支付下单的过程中几分钟之后才得到结果。那么我们只需要通知短信系统“我们支付成功了”,不一定非要等待它处理完成。 - 流量削峰
试想上下游对于事件的处理能力是不同的。比如,Web前端每秒承受上千万的请求,并不是什么神奇的事情,只需要加多一点机器,再搭建一些LVS负载均衡设备和Nginx等即可。但数据库的处理能力却十分有限,即使使用SSD加分库分表,单机的处理能力仍然在万级。由于成本的考虑,我们不能奢求数据库的机器数量追上前端。
这种问题同样存在于系统和系统之间,如短信系统可能由于短板效应,速度卡在网关上(每秒几百次请求),跟前端的并发量不是一个数量级。但用户晚上个半分钟左右收到短信,一般是不会有太大问题的。如果没有消息队列,两个系统之间通过协商、滑动窗口等复杂的方案也不是说不能实现。但系统复杂性指数级增长,势必在上游或者下游做存储,并且要处理定时、拥塞等一系列问题。而且每当有处理能力有差距的时候,都需要单独开发一套逻辑来维护这套逻辑。所以,利用中间系统转储两个系统的通信内容,并在下游系统有能力处理这些消息的时候,再处理这些消息,是一套相对较通用的方式。 - 广播
消息队列的基本功能之一是进行广播。如果没有消息队列,每当一个新的业务方接入,我们都要联调一次新接口。有了消息队列,我们只需要关心消息是否送达了队列,至于谁希望订阅,是下游的事情,无疑极大地减少了开发和联调的工作量。 - 最终一致性
最终一致性指的是两个系统的状态保持一致,要么都成功,要么都失败。当然有个时间限制,理论上越快越好,但实际上在各种异常的情况下,可能会有一定延迟达到最终一致状态,但最后两个系统的状态是一样的。
业界有一些为“最终一致性”而生的消息队列,如Notify(阿里)、QMQ(去哪儿)等,其设计初衷,就是为了交易系统中的高可靠通知。
本地事务维护业务变化和通知消息,一起落地(失败则一起回滚),然后RPC到达broker,在broker成功落地后,RPC返回成功,本地消息可以删除。否则本地消息一直靠定时任务轮询不断重发,这样就保证了消息可靠落地broker。
broker往consumer发送消息的过程类似,一直发送消息,直到consumer发送消费成功确认。
总结:
消息队列不是万能的。对于需要强事务保证而且延迟敏感的,RPC是优于消息队列的。
对于一些无关痛痒,或者对于别人非常重要但是对于自己不是那么关心的事情,可以利用消息队列去做。
支持最终一致性的消息队列,能够用来处理延迟不那么敏感的“分布式事务”场景,而且相对于笨重的分布式事务,可能是更优的处理方式。
当上下游系统处理能力存在差距的时候,利用消息队列做一个通用的“漏斗”。在下游有能力处理的时候,再进行分发。
为什么要选择RabbitMQ
- 基于AMQP协议
- 高并发
- 高性能
- 高可用
- 强大的社区支持,以及很多公司都在使用
- 支持插件
- 支持多语言
AMQP协议介绍
出现背景
越是大型的公司越是不可避免的使用来自众多供应商的MQ产品,来服务企业内部的不同应用。如果应用已经订阅了TIBCO MQ信息,若突然需要消费来自IBM MQ的消息,则实现起来会非常困难。这些产品使用不同的api,不同的协议,因而毫无疑问无法联合起来组成单一的总线。为了解决这个问题,Java Message Service(JMS)在2001年诞生了。JMS试图通过提供公共java api的方式,隐藏单独MQ产品供应商提供的实际接口,从而跨越了壁垒和解决了互通问题。从技术上讲,java应用程序只需要对JMS API编程,选择合适的MQ驱动即可。JMS会打理好其他部分的。问题是你在尝试使用单独编准化接口来整合众多不同的接口。这就像是把不同的类型的衣服粘在一起:缝合处终究会裂开。使用JMS(Java Message Service)的应用程序会变得更加脆弱。我们需要新的消息通信标准化方案。
-
高级消息队列协议(AMQP)是面向消息的中间件的开放标准应用层协议。 AMQP的特征是消息导向,排队,路由(包括点对点和发布和订阅),可靠性和安全性。
-
AMQP要求消息传递提供商和客户端的行为在不同供应商实现可互操作的情况下,以与SMTP,HTTP,FTP等相同的方式创建了可互操作的系统。 中间件的以前标准化发生在API级别(例如JMS),并且专注于使程序员与不同中间件实现的交互标准化,而不是提供多个实现之间(AMQP的实现)的互操作性。与定义API和消息传递实现必须提供的一组行为的JMS不同,AMQP是线级协议。 线级协议是以网络流作为字节流发送的数据格式的描述。 因此,无论实现语言如何,任何可以创建和解释符合此数据格式的消息的工具都可以与任何其他兼容工具进行互操作。
-
AMQP协议是具有现代特征的二进制协议。一个提供统一消息服务的应用层标准高级消息队列协议,是应用层协议的一个开发标准,为面向消息的中间件设计。基于此协议的客户端与消息中间件可传递消息,并不受客户端/中间件不同产品,不同开发语言等条件的限制。
-
AMQP是一种二进制应用层协议,旨在有效地支持各种消息应用和通信模式。 它提供流控制的面向消息的通信,其中包括消息传递保证,例如最多一次(每个消息被投递一次或从不投递消息),至少一次(每个消息肯定要被传递,但可以在不同的时间)和确定一次(其中消息将始终确定到达并仅执行一次),以及基于SASL和/或TLS的身份验证和/或加密。 它假定一个基本的可靠传输层协议,如传输控制协议(TCP)。
-
AMQP规范定义在几个层次中:(i)类型系统(传递的消息类型),(ii)用于将消息从一个进程转移到另一个进程的对称异步协议,(iii)标准的可扩展消息格式(iv)一系列的标准化但可扩展的“消息传递功能”。
一些概念梳理
- Server:又称为Broker。接收客户端连接,实现AMQP的服务器实体。
- Connection:连接,应用程序与Broker的网络连接。
- Channel:信道,几乎所有的操作都在Channel中进行,Channel是进行消息读写的通道。客户端可建立多个Channel,每个Channel代表一个会话任务。
- Message:消息。服务器和应用程序之间传递的数据,本质上就是一段数据,由Properties和Body组成。
- Exchange:交换机。接收消息,根据路由键转发消息到绑定的队列。
- Binding:Exchange和Queue之间的虚拟连接,binding中可以包含routing key。
- Routing key:一个虚拟地址,虚拟机可用它来确定如何路由一个特定消息。
- Queue:也称为Message Queue,消息队列,保存消息并将它们转发给消费者。
- Virtual Host:其实是一个虚拟概念。类似于权限控制组,一个Virtual Host里面可以有若干个Exchange和Queue,可以用来隔离Exchange和Queue。,同一个Virtual Host里面不能有相同名称的Exchange和Queue。但是权限控制的最小粒度是Virtual Host。(下面会讲到)

总结:
生产者将消息发送到Exchange交换机的,不是发送到Queue上的,生产者不知道消息是谁消费,有哪些消费者消费。Exchange根据一定的路由规则将消息转发到Queue。
消费者是监听队列的,不知道是哪个生产者发送的。
AMQP我的理解
一个开放的面向消息中间件的协议,所有此协议的实现可以进行互相操作,无论实现语言如何,任何符合此协议的数据格式的消息工具都可以与任何其他兼容工具进行互操作。而以前JMS(Java Message Service),将不同的中间件的实现进行API层次的标准化。
-------------------------------------------------------------------------------------------------
RabbitMQ的安装
RabbitMQ是由LShift提供的一个Advanced Message Queuing Protocol(AMQP)的开源实现,由以高性能,健壮以及可伸缩性出名的Erlang写成,因此也继承了这些优点。
二进制的安装方式,
我本地选择131这台服务器进行安装,修改hostname
[root@localhost ~]# ifconfig
eth1 Link encap:Ethernet HWaddr 00:50:56:2F:74:85
inet addr:192.168.1.131 Bcast:192.168.1.255 Mask:255.255.255.0
inet6 addr: fe80::250:56ff:fe2f:7485/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:22129 errors:0 dropped:0 overruns:0 frame:0
TX packets:8960 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:29664818 (28.2 MiB) TX bytes:581671 (568.0 KiB)
lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
inet6 addr: ::1/128 Scope:Host
UP LOOPBACK RUNNING MTU:16436 Metric:1
RX packets:4 errors:0 dropped:0 overruns:0 frame:0
TX packets:4 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:240 (240.0 b) TX bytes:240 (240.0 b)
修改hostname
[root@localhost ~]# cd /etc/sysconfig/
[root@localhost sysconfig]# vim network
配置如下:
NETWORKING=yes
HOSTNAME=mqserver
修改hosts
[root@localhost sysconfig]# vim /etc/hosts
配置如下:
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
192.168.1.131 mqserver
关闭防火墙:
[root@localhost sysconfig]# chkconfig iptables off
重启一下机器:
[root@localhost sysconfig]# reboot
将下载好的rabbitmq-server-3.6.10-1.el6.noarch.rpm
放到指定的目录下/usr/local/software
安装rabbitmq-server
[root@mqserver software]# rpm -ivh rabbitmq-server-3.6.10-1.el6.noarch.rpm
warning: rabbitmq-server-3.6.10-1.el6.noarch.rpm: Header V4 RSA/SHA512 Signature, key ID 6026dfca: NOKEY
error: Failed dependencies:
erlang >= R16B-03 is needed by rabbitmq-server-3.6.10-1.el6.noarch
socat is needed by rabbitmq-server-3.6.10-1.el6.noarch
缺少erlang-18.3-1.el6.x86_64.rpm
的依赖,到RabbitMQ的指定目录下去下载将erlang-18.3-1.el6.x86_64.rpm
也上传至指定目录,
erlang-18.2-1.el6.x86_64.rpm
针对centos6.*
版本的,erlang-18.2-1.el7.centos.x86_64.rpm
针对的centos7.*
版本
安装erlang
[root@mqserver software]# rpm -ivh erlang-18.3-1.el6.x86_64.rpm
注意安装erlang的时候有时候会报缺少包之类的错误,可以先执行下面的命令先下载好整个linux系统的一些依赖:
[root@mqserver software]# yum -y install make gcc gcc-c++ kernel-devel m4 ncurses-devel openssl-devel
验证Erlang是否安装成功
[root@mqserver software]# erl
Erlang/OTP 18 [erts-7.3] [source] [64-bit] [async-threads:10] [hipe] [kernel-poll:false]
Eshell V7.3 (abort with ^G)
1>
再次去安装RabbitMQ服务
[root@mqserver software]# rpm -ivh rabbitmq-server-3.6.10-1.el6.noarch.rpm
warning: rabbitmq-server-3.6.10-1.el6.noarch.rpm: Header V4 RSA/SHA512 Signature, key ID 6026dfca: NOKEY
error: Failed dependencies:
socat is needed by rabbitmq-server-3.6.10-1.el6.noarch
再次提醒我们有一些依赖没有安装,将socat-1.7.3.2-1.el6.lux.x86_64.rpm
上传至当前目录
安装socat
[root@mqserver software]# rpm -ivh socat-1.7.3.2-1.el6.lux.x86_64.rpm
再去安装rabbitmq
[root@mqserver software]# rpm -ivh rabbitmq-server-3.6.10-1.el6.noarch.rpm
启动rabbitmq服务:
[root@mqserver software]# cd /etc/init.d
[root@mqserver init.d]# ./rabbitmq-server restart
Restarting rabbitmq-server: RabbitMQ is not running
SUCCESS
rabbitmq-server.
查看默认端口5672(默认端口)是否启动,
[root@mqserver init.d]# lsof -i:5672
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
beam 2793 rabbitmq 49u IPv6 35431 0t0 TCP *:amqp (LISTEN)
二进制方式安装方式总结:
- 安装erlang
- 安装socat
- 安装rabbitmq
使用tar包安装
本地使用133服务器进行安装
查看网卡
[root@mqserver software]# ifconfig
eth1 Link encap:Ethernet HWaddr 00:50:56:2F:EC:B5
inet addr:192.168.1.133 Bcast:192.168.1.255 Mask:255.255.255.0
inet6 addr: fe80::250:56ff:fe2f:ecb5/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:72432 errors:0 dropped:0 overruns:0 frame:0
TX packets:38885 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:95728391 (91.2 MiB) TX bytes:2941953 (2.8 MiB)
lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
inet6 addr: ::1/128 Scope:Host
UP LOOPBACK RUNNING MTU:16436 Metric:1
RX packets:10 errors:0 dropped:0 overruns:0 frame:0
TX packets:10 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:744 (744.0 b) TX bytes:744 (744.0 b)
修改hostname
[root@localhost ~]# cd /etc/sysconfig/
[root@localhost sysconfig]# vim network
配置如下:
NETWORKING=yes
HOSTNAME=mqserver
修改hosts
[root@localhost sysconfig]# vim /etc/hosts
配置如下:
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
192.168.1.133 mqserver
关闭防火墙:
[root@localhost sysconfig]# chkconfig iptables off
重启一下机器:
[root@localhost sysconfig]# reboot
将rabbitmq-server-generic-unix-3.6.10.tar.xz
和erlang-18.3-1.el6.x86_64.rpm
文件上传到指定目录下(/usr/local/software)
安装erlang,跟上面一样先安装一些依赖
[root@mqserver software]# yum -y install make gcc gcc-c++ kernel-devel m4 ncurses-devel openssl-devel
再去安装erlang
[root@mqserver software]# rpm -ivh erlang-18.3-1.el6.x86_64.rpm
解压tar包(关于tar的下载地址也在博客最上面的链接上)
[root@mqserver software]# tar -xvf rabbitmq-server-generic-unix-3.6.10.tar.xz
进入解压后的sbin目录下:
[root@mqserver software]# cd rabbitmq_server-3.6.10/sbin
[root@mqserver sbin]# ll
total 44
-rwxr-xr-x. 1 1023 1023 1480 May 25 06:55 rabbitmqctl
-rwxr-xr-x. 1 1023 1023 1885 May 25 06:55 rabbitmq-defaults
-rwxr-xr-x. 1 1023 1023 12095 May 25 06:55 rabbitmq-env
-rwxr-xr-x. 1 1023 1023 1362 May 25 06:55 rabbitmq-plugins
-rwxr-xr-x. 1 1023 1023 10971 May 25 06:55 rabbitmq-server
[root@mqserver sbin]# ./rabbitmq-server &
[1] 2127
[root@mqserver sbin]#
RabbitMQ 3.6.10. Copyright (C) 2007-2017 Pivotal Software, Inc.
## ## Licensed under the MPL. See http://www.rabbitmq.com/
## ##
########## Logs: /usr/local/software/rabbitmq_server-3.6.10/var/log/rabbitmq/rabbit@mqserver.log
###### ## /usr/local/software/rabbitmq_server-3.6.10/var/log/rabbitmq/rabbit@mqserver-sasl.log
##########
Starting broker...
completed with 0 plugins.
检查rabbitmq是否启动
[root@mqserver sbin]# lsof -i:5672
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
beam 2216 root 48u IPv6 17882 0t0 TCP *:amqp (LISTEN)
停止服务:
[root@mqserver sbin]# ./rabbitmqctl stop
使用./rabbitmq-server -detached 也是后台启动
[root@mqserver sbin]# ./rabbitmq-server -detached
Warning: PID file not written; -detached was passed.
[root@mqserver sbin]# lsof -i:5672
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
beam 2601 root 48u IPv6 19438 0t0 TCP *:amqp (LISTEN)
编写二个脚本:start.sh
,stop.sh
[root@mqserver sbin]# vim start.sh
内容是
./rabbitmq-server -detached
[root@mqserver sbin]# vim stop.sh
内容是
./rabbitmqctl stop
授权,可以使用这二个脚本进行mq的启动和停止
[root@mqserver sbin]# chmod 777 start.sh stop.sh
[root@mqserver sbin]# ./stop.sh
Stopping and halting node rabbit@mqserver
[root@mqserver sbin]# lsof -i:5672
[root@mqserver sbin]# ./start.sh
Warning: PID file not written; -detached was passed.
[root@mqserver sbin]# lsof -i:5672
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
beam 3017 root 48u IPv6 20001 0t0 TCP *:amqp (LISTEN)
RabbitMQ命令的基本操作
查看rabbitmq-server的所在位置,以下三个命令仅在二进制安装方式下有效
[root@mqserver ~]# type rabbitmq-server
rabbitmq-server is /usr/sbin/rabbitmq-server
管理插件的命令:
[root@mqserver sbin]# type rabbitmq-plugins
rabbitmq-plugins is hashed (/usr/sbin/rabbitmq-plugins)
rabbitmqctl指令的位置,rabbitmqctl指令很强大,下面我们会讲到
[root@mqserver ~]# type rabbitmqctl
rabbitmqctl is /usr/sbin/rabbitmqctl
了解一下强大的命令:rabbitmqctl
rabbitmqctl status:查看rabbitmq的运行状态。
[root@iZbp1jcwx7sfb1nwzrehy6Z sbin]# rabbitmqctl status
查看rabbitmqctl所有的命令
[root@mqserver ~]# rabbitmqctl
比如下面这些,查看当前mq的队列,exchanges,connections,channels,consumers等等
list_queues [-p <vhost>] [--offline|--online|--local] [<queueinfoitem> ...]
list_exchanges [-p <vhost>] [<exchangeinfoitem> ...]
list_bindings [-p <vhost>] [<bindinginfoitem> ...]
list_connections [<connectioninfoitem> ...]
list_channels [<channelinfoitem> ...]
list_consumers [-p <vhost>]
status
查看queues,刚开始安装rabbitmq的时候没有队列:
[root@mqserver init.d]# rabbitmqctl list_queues
Listing queues
查看exchanges
[root@mqserver init.d]# rabbitmqctl list_exchanges
Listing exchanges
amq.direct direct
direct
amq.match headers
amq.rabbitmq.log topic
amq.topic topic
amq.headers headers
amq.rabbitmq.trace topic
amq.fanout fanout
查看bingding,刚安装服务的时候也没有binding
[root@mqserver init.d]# rabbitmqctl list_bindings
Listing bindings
查看一些用户:
[root@mqserver init.d]# rabbitmqctl list_users
Listing users
guest [administrator]
查看vhosts
[root@mqserver init.d]# rabbitmqctl list_vhosts
Listing vhosts
/
添加一个用户:
[root@mqserver init.d]# rabbitmqctl add_user zhihao.miao 123456
Creating user "zhihao.miao"
[root@mqserver init.d]# rabbitmqctl list_users
Listing users
zhihao.miao []
guest [administrator]
此时发现zhihao.miao这个用户还没有权限。
设置权限,设置完成之后发现设置成功:
[root@mqserver init.d]# rabbitmqctl set_user_tags zhihao.miao administrator
Setting tags for user "zhihao.miao" to [administrator]
[root@mqserver init.d]# rabbitmqctl list_users
Listing users
zhihao.miao [administrator]
guest [administrator]
删除用户:
[root@iZbp1jcwx7sfb1nwzrehy6Z sbin]# rabbitmqctl delete_user zhihao.miao
Deleting user "admin"
[root@iZbp1jcwx7sfb1nwzrehy6Z sbin]# rabbitmqctl list_users
Listing users
guest [administrator]
停止rabbitmq
./rabbitmqctl stop
rabbitmq的参数设置
RabbitMQ配有默认内置设置。 在某些环境(例如开发和质量保证)中,这些可以是完全足够的。 如果运行正常,则可能根本不需要任何配置。 但是在一些情况下,我们需要配置一些参数区分于默认的配置。
比如rabbitmq的默认端口是5672,如何去改变它呢?
三种配置参数的方法
- 环境变量 Environment Variables
- 配置文件 Configuration File的方式(最常用的方式)
- 运行期更改参数和策略 Runtime Parameters and Policies
比如我想想rabbitmq默认的使用端口5672改为5673,那么怎么操作,使用配置文件 Configuration File的方式。
RabbitMQ核心应用, Erlang 服务and RabbitMQ 插件都会使用rabbitmq.config
进行相关参数配置。
如果是Generic UNIX
安装方式在$RABBITMQ_HOME/etc/rabbitmq/
的目录下放置rabbitmq.config
RPM的安装方式那么就在/etc/rabbitmq/
目录下放置rabbitmq.config
我的192.168.1.131
服务器上就是使用的RPM的安装方式,
vim rabbitmq.config
配置方式:
[
{rabbit, [{tcp_listeners, [5673]}]}
].
官网提供了一份rabbitmq.config示列,此示例文件包含您可能想要设置的大多数配置项(省略一些非常模糊的配置)以及这些设置的文档的示例。 所有配置项都在示例中注释掉,因此您可以取消注册所需的内容。请注意,不要将其当作一般的推荐配置。
其他的配置:

插件的安装
查看当前可以安装的插件(使用tar安装的进入相关的解压包下的sbin目录):
[root@mqserver sbin]# cd /usr/sbin/
[root@mqserver sbin]# ./rabbitmq-plugins list
Configured: E = explicitly enabled; e = implicitly enabled
| Status: * = running on rabbit@mqserver
|/
[ ] amqp_client 3.6.10
[ ] cowboy 1.0.4
[ ] cowlib 1.0.2
[ ] rabbitmq_amqp1_0 3.6.10
[ ] rabbitmq_auth_backend_ldap 3.6.10
[ ] rabbitmq_auth_mechanism_ssl 3.6.10
[ ] rabbitmq_consistent_hash_exchange 3.6.10
[ ] rabbitmq_event_exchange 3.6.10
[ ] rabbitmq_federation 3.6.10
[ ] rabbitmq_federation_management 3.6.10
[ ] rabbitmq_jms_topic_exchange 3.6.10
[ ] rabbitmq_management 3.6.10
[ ] rabbitmq_management_agent 3.6.10
[ ] rabbitmq_management_visualiser 3.6.10
[ ] rabbitmq_mqtt 3.6.10
[ ] rabbitmq_recent_history_exchange 3.6.10
[ ] rabbitmq_sharding 3.6.10
[ ] rabbitmq_shovel 3.6.10
[ ] rabbitmq_shovel_management 3.6.10
[ ] rabbitmq_stomp 3.6.10
[ ] rabbitmq_top 3.6.10
[ ] rabbitmq_tracing 3.6.10
[ ] rabbitmq_trust_store 3.6.10
[ ] rabbitmq_web_dispatch 3.6.10
[ ] rabbitmq_web_mqtt 3.6.10
[ ] rabbitmq_web_mqtt_examples 3.6.10
[ ] rabbitmq_web_stomp 3.6.10
[ ] rabbitmq_web_stomp_examples 3.6.10
[ ] sockjs 0.3.4```
安装管控页面:
[root@mqserver sbin]# ./rabbitmq-plugins enable rabbitmq_management
卸载插件:
[root@mqserver sbin]# ./rabbitmq-plugins enable rabbitmq_management
安装管控台之后,rabbitmq的web管控台默认占用的端口是15672
[root@mqserver sbin]# lsof -i:15672
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
beam 3432 rabbitmq 50r IPv4 25122 0t0 TCP *:15672 (LISTEN)
默认的用户名密码是guest,guest,但是只能在localhost:15672或者127.0.0.1:15672上登录。
如何让guest来进行ip登录呢?
loopback用户,只能用localhost,127.0.0.1地址登录。如果将自己设置的用户加入到loopback_users,那么此时该用户也只能通过localhost,127.0.0.1地址进行登录了。
[root@mqserver sbin]# cd /etc/rabbitmq/
[root@mqserver rabbitmq]# vim rabbitmq.config
rabbitmq.config的内容如下,
[
{rabbit, [{tcp_listeners, [5672]},{loopback_users,[]}]}
].
重启rabbitmq服务,
[root@mqserver software]# cd /etc/init.d
[root@mqserver init.d]# ./rabbitmq-server restart
配置之后就可以使用guest用户访问http://192.168.1.131:15672/#
就可以了。
-------------------------------------------------------------------------------------------------
Exchange概念
Exchange:交互机,根据路由键转发消息到绑定的队列。

自己说说Exchange在RabbitMQ消息中间件中的作用:
服务器发送消息不会直接发送到队列中(Queue),而是直接发送给交换机(Exchange),然后根据确定的规则,RabbitMQ将会决定消息该投递到哪个队列。这些规则称为路由键(routing key),队列通过路由键绑定到交换机上。消息发送到服务器端(broker),消息也有自己的路由键(也可以是空),RabbitMQ也会将消息和消息指定发送的交换机的绑定(binding,就是队列和交互机的根据路由键映射的关系)的路由键进行匹配。如果匹配的话,就会将消息投递到相应的队列。
Exchange的类型主要有四种,分别是
Direct Exchange:将消息中的
Routing key
与该Exchange
关联的所有Binding
中的Routing key
进行比较,如果相等,则发送到该Binding
对应的Queue
中。Topic Exchange:将消息中的
Routing key
与该Exchange
关联的所有Binding
中的Routing key
进行对比,如果匹配上了,则发送到该Binding
对应的Queue
中。Fanout Exchange:直接将消息转发到所有
binding
的对应queue
中,这种exchange
在路由转发的时候,忽略Routing key
。Headers Exchange:将消息中的
headers
与该Exchange
相关联的所有Binging
中的参数进行匹配,如果匹配上了,则发送到该Binding
对应的Queue
中。
查看exchanges属性,在管控台上查看http://192.168.1.131:15672/#/exchanges


相关属性的说明,如果有多个Virtual host,则还会有Virtual host属性。一般默认的Virtual host是"/",我们知道Virtual host可以做最小粒度的权限控制。

- Virtual host:属于哪个Virtual host。
- Name:名字,同一个Virtual host里面的Name不能重复。
- Durability: 是否持久化,Durable:持久化。Transient:不持久化。
- Auto delete:当最后一个绑定(队列或者exchange)被unbind之后,该exchange自动被删除。
- Internal: 是否是内部专用exchange,是的话,就意味着我们不能往该exchange里面发消息。
- Arguments: 参数,是AMQP协议留给AMQP实现做扩展使用的。
alternate_exchange配置的时候,exchange根据路由路由不到对应的队列的时候,这时候消息被路由到指定的alternate_exchange的value值配置的exchange上。(下面的博客会有说明这参数的具体使用)


unbing之后该exchange删除。
命令行查看exchange信息
使用命令查看exchanges列表,默认的Virtual host
[root@mqserver ~]# rabbitmqctl list_exchanges
Listing exchanges
amq.direct direct
direct
amq.match headers
amq.rabbitmq.log topic
amq.topic topic
amq.headers headers
amq.rabbitmq.trace topic
amq.fanout fanout
指定某个Virtual host的exchanges列表,我指定的事默认的Virtual host(/)
[root@mqserver ~]# rabbitmqctl list_exchanges -p /
Listing exchanges
amq.direct direct
direct
amq.match headers
amq.rabbitmq.log topic
amq.topic topic
amq.headers headers
amq.rabbitmq.trace topic
amq.fanout fanout
使用restful api
查看exchanges列表,api的文档地址,(http://192.168.1.131:15672/api/
)
对应着下面的链接,当前管控台的url/api

具体的地址,输入对应的用户名和密码,看到对应用户的exchanges
列表
http://192.168.1.131:15672/api/exchanges
Direct Exchange
将消息中的Routing key
与该Exchange
关联的所有Binding
中的Routing key
进行比较,如果相等,则发送到该Binding
对应的Queue
中。
- 一个
Exchange
可以Binding
一个或多个Queue
。 - 绑定可以指定
Routing key
,Binding
的多个Queue
可以使用相同的Routing key
,也可以使用不同的Routing key
。

创建三个Exchange
,名称分别是login
,logout
,register
三个exchange。
创建几个Queue
,名称分别是PC
,WAP
,APP
,OA
。
指定它们的Binding
关系,
测试:

查看队列中的消息

其他的可自行测试
特别的Exchange
默认的Exchange(名字为空,AMQP default)
- 默认的
Exchange
不能进行Binding
操作 - 任何发送到该
Exchange
的消息都会被转发到Routing key
指定的Queue
中 - 如果
vhost
中不存在Routing key
中指定的队列名,则该消息会被抛弃。


Topic Exchange
将消息中的Routing key
与该Exchange
关联的所有Binding
中的Routing key
进行对比,如果匹配上了,则发送到该Binding
对应的Queue
中。
匹配规则
* 匹配一个单词
# 匹配0个或多个字符
*,# 只能写在.号左右,且不能挨着字符
单词和单词之间需要用.隔开。
列子
- Routing key是user.log.#,因为#是匹配0个或多个字符,所以下面的可以匹配:
user.log
user.log.info
user.log.a
user.log.info.login
- Routing key是user.log.,因为 匹配一个单词,所以
user.log.info 可以匹配
user.log 不能匹配
user.log.info.login 不能匹配,二个单词
- Routing key是#.log.#
可以匹配:
log
user.log
log.info
user.log.info
user.log.info.a
- Routing key是.log.
log 不匹配
user.log 不匹配
log.info 不匹配
user.log.info 匹配,前后各一个单词
user.log.info.a 不匹配
a.user.log.info 不匹配
- Routing key是*.action.#
action 不符合
action.log 不符合
user.action.log 符合
user.action.log.info 符合
user.action 符合
user.log.action 不符合
- Routing key是#.action.*
action 不符合
user.action 不符合
user.action.action 符合
user.action.login 符合
user.action.login.count 不符合
- Routing key是* 表示匹配一个单词
- Routing key是#,或者#.# 表示匹配所有
如果指定了Exchange是Topic类型的,但是相应的Binding
中的Routing key *
,#
都没有,则相等才转发,类似于Direct Exchange
如果Binding
中的Routing key
为#
或者#.#
,则全部转发,类似Fanout Exchange
(下面会讲到)
测试:
建立一个名称为log
的topic
类型的Exchange
新建三个队列q1
,q2
,q3
分别绑定 *
,#
,#.#

自己定义一脚本,便于测试的时候清除所有队列的消息:
cd /u01
vim purge.sh
curl -X DELETE -u zhihao.miao:123456 http://192.168.1.131:15672/api/queues/%2F/q1/contents
curl -X DELETE -u zhihao.miao:123456 http://192.168.1.131:15672/api/queues/%2F/q2/contents
curl -X DELETE -u zhihao.miao:123456 http://192.168.1.131:15672/api/queues/%2F/q3/contents
curl -X DELETE -u zhihao.miao:123456 http://192.168.1.131:15672/api/queues/%2F/action_queue/contents
curl -X DELETE -u zhihao.miao:123456 http://192.168.1.131:15672/api/queues/%2F/log2_queue/contents
curl -X DELETE -u zhihao.miao:123456 http://192.168.1.131:15672/api/queues/%2F/log_queue/contents
curl -X DELETE -u zhihao.miao:123456 http://192.168.1.131:15672/api/queues/%2F/sys_log_info_queue/contents
curl -X DELETE -u zhihao.miao:123456 http://192.168.1.131:15672/api/queues/%2F/sys_log_queue/contents
curl -X DELETE -u zhihao.miao:123456 http://192.168.1.131:15672/api/queues/%2F/user2_queue/contents
curl -X DELETE -u zhihao.miao:123456 http://192.168.1.131:15672/api/queues/%2F/user_action_queue/contents
curl -X DELETE -u zhihao.miao:123456 http://192.168.1.131:15672/api/queues/%2F/user_log_debug_queue