一、RabbitMQ初识
1、中间件(Middleware):直白的理解就是处于中间(一般是操作平台与应用软件之间)的并且担任沟通角色的一种软件。在J2EE领域中,中间件其实就是JMS技术标准的一种具体的实现产品(类似于JDBC与具体数据库驱动或者JPA与具体的ORM产品,如Hibernate、Toplink的关系)。
2、RabbitMQ到底是啥鬼东西?
他是一个消息中间件(Middleware),或者说是一个消息代理(Message Broker); 是AMQP(advanced message queueing protocol)的开源实现,其核心模型就是:“生产者”——“消费者”(可以说所有的消息中间件都是这个模型);其底层使用ErLang语言。
二、RabbitMQ环境构建
1、下载安装
A、RabbitMQ的官网:http://www.rabbitmq.com/,进入官网后其页面中有一个版块
“Get Started”,该模块中有提供各种形式的、各种操作平台的下载包。
进入download模块,会看见如下部分:
在本文形成时使用的是最新的版本3.5.1如图:下载windows平台的安装包zip格式(当然你也可以选择exe格式的,自己做主吧)
B、解压缩(安装)下载包到本地磁盘,本文档放到了目录:D:\rabbitmq_server-3.5.1,其文件目录结构如下:
注意:D:\rabbitmq_server-3.5.1下有一个read-me.txt及etc目录下也有一个README,建议先浏览下,至于其他每个子文件夹的内容自己了解吧
C、为了方便命令行操作,建议将sbin加入path环境中
好了,至此,经验告诉我们安装已然结束了,可以开玩了(但其实并没有,不要心急,慢慢往下看)
2、启动RabbitMQ
首先看下加入path的目录下有啥玩意啊:
看名字,大概可以猜出来干啥的,好了要玩rabbit,首先肯定要让那家伙跑起来才是啊。看文档发现就是rabbitmq-server.bat(跟猜的一样),好了windows+r 进入cmd后执行rabbitmq-server发现报错,起不来具体信息如下:
看了提示信息,这才恍然大悟,rabbitmq使用二郎语言开发的(前面有提到吧),那他肯定依赖二郎的环境了,啥也别说了,装erlang吧。其实如果你用的是exe格式的安装包,那么执行时会检测erlang环境的,检测不到,会提示你安装erlang的,读者可以试试exe形式的。
erlang安装(这是本人安装的版本),千万记得设置ERLANG_HOME环境变量哦
至此,rabbitmq的安装完成。
三RabbitMQ启停管理及其他
第二部分中我们安装了rabbitmq及其依赖的环境,现在可以小试下rabbitmq了。
1、启动服务器
Rabbitmq启动:执行安装目录sbin下的rabbitmq-server来启动:
2、Rabbitmq治理
1中我们启动了rabbitmq,但是有没有可以直接管理的界面ui啊,看rabbitmq官网doc部分,发现三种管理途径:
A、rabbitmq网页管理ui: http://server-name:15672/,server-name在本机的话,一般默认都是localhost, 默认登陆用户:guest/guest
B、基于http的 rabbitmqadmin工具(该工具需要python支持)
C、rabbitmqctl:这是rabbitmq的命令行管理工具,在sbin目录下
此处我们看一下网页版的管理访问:
访问地址:http://localhost:15672/,弹出如下界面,要求登录:
输入guest/guest登入,登入后界面如下,自己点一点吧。
四、RabbitMQ通信
1、RabbitMQ内部对象认识
既然RabbitMQ是消息中间件,是生产者——消费者模式,那我们应该测测看啊。好了,在开始消息测试之前,首先这里有几个名词需要熟悉。
Broker:简单来说就是消息队列服务器实体。
channel:消息通道,在客户端的每个连接里,可建立多个channel,每个channel代表一个会话任务
Exchange:消息交换机,它指定消息按什么规则,路由到哪个队列
Queue:消息载体,生产者产出的消息就是放在它里面的。
Binding:绑定,它的作用就是把exchange和queue按照路由规则绑定起来,起过滤的作用(后面说)
Routing Key:路由关键字,exchange根据这个关键字进行消息投递。
vhost:虚拟主机,一个broker里可以开设多个vhost,用作不同用户的权限分离
producer:消息生产者,就是投递消息的程序
consumer:消息消费者,就是接受消息的程序
2、RabbitMQ之简单java收发消息
RabbitMQ 是一个消息代理。这主要的原理十分简单,就是通过接受和转发消息。你可以把它想象成邮局:当你将一个包裹送到邮局,你会相信邮递员先生最终会将邮件送到接件人手上。RabbitMQ就好比一个邮箱,邮局或邮递员。邮局和RabbitMQ两种主要的不同之处在于,RabbitMQ不处理文件,而是接受,并存储和以二进制形式将消息转发。(官网译本)
说白了就是,用两个程序连接RabbitMQ,然后一个向mq发送消息,另一个去取消息。
P—生产者 c—消费者 红色为队列
1、java收发消息
在这里我们需要写两个java程序,一个用来发消息,一个用来读消息。这里我们利用maven项目来测试
A、下载RabbitMQ客户端开发需要的依赖:http://www.rabbitmq.com/java-client.html,同时,官方也提供了maven的依赖坐标:
com.rabbitmq
amqp-client
3.5.1
生产者:
消费者:
ConnectionFactory、Connection、Channel都是RabbitMQ对外提供的API中最基本的对象。Connection是RabbitMQ的socket链接,它封装了socket协议相关部分逻辑。ConnectionFactory为Connection的制造工厂。
Channel是我们与RabbitMQ打交道的最重要的一个接口,我们大部分的业务操作是在Channel这个接口中完成的,包括定义Queue、定义Exchange、绑定Queue与Exchange、发布消息等。
运行上述代码,可以在web ui中观察RabbitMQ中的各种对象的状态。
3、消息传递细节
RabbitMQ消息接收过程:
由上图可以看出,消息不是直接到队列的,而是经过Exchange转发到队列的,这就是RabbitMq的特别之处——生产者只能将消息发送给Exchange(交换机)。
在RabbitMq中Exchange是个重要角色。
交换机Exchange:它从生产者那里接收消息,另一边将消息推送到队列中。要求exchange必须清楚的知道它所接收到的消息要如何处理——是否将它附加到一个特别的队列中?是否将消息推送到多个队列中?或者是否它应该被丢弃。规则的定义是由交换类型及Binding共同决定的。
Exchange类型:
Direct:direct类型的Exchange路由规则很简单,它会把消息路由到那些binding key与routing key完全匹配的Queue中
Topic:字面意思是主题,其实就是发布订阅模式,换句话说就是只要发来的消息中有队列感兴趣的内容,哪怕是消息的一部分,他也接受,其中有如下约束:
routing key为一个句点号“. ”分隔的字符串(我们将被句点号“. ”分隔开的每一段独立的字符串称为一个单词),如“stock.usd.nyse”、“nyse.vmw”、“quick.orange.rabbit”,binding key与routing key一样也是句点号“. ”分隔的字符串,binding key中可以存在两种特殊字符“*”与“#”,用于做模糊匹配,其中“*”用于匹配一个单词,“#”用于匹配多个单词(可以是零个)。
Headers:headers类型的Exchange不依赖于routing key与binding key的匹配规则来路由消息,而是根据发送的消息内容中的headers属性进行匹配,在绑定Queue与Exchange时指定一组键值对;当消息发送到Exchange时,RabbitMQ会取到该消息的headers(也是一个键值对的形式),对比其中的键值对是否完全匹配Queue与Exchange绑定时指定的键值对;如果完全匹配则消息会路由到该Queue,否则不会路由到该Queue。
Fanout:fanout类型的Exchange路由规则非常简单,它会把所有发送到该Exchange的消息路由到所有与它绑定的Queue中。
routing key:生产者在将消息发送给Exchange的时候,一般会指定一个routing key,来指定这个消息的路由规则,而这个routing key需要与Exchange Type及binding key联合使用才能最终生效。在Exchange Type与binding key固定的情况下(在正常使用时一般这些内容都是固定配置好的),我们的生产者就可以在发送消息给Exchange时,通过指定routing key来决定消息流向哪里。RabbitMQ为routing key设定的长度限制为255 bytes。
Binding:RabbitMQ中通过Binding将Exchange与Queue关联起来,这样RabbitMQ
就知道如何正确地将消息路由到指定的Queue了
Bindingkey:在绑定(Binding)Exchange与Queue的同时,一般会指定一个binding key;消费者将消息发送给Exchange时,一般会指定一个routing key;当binding key与routing key相匹配时,消息将会被路由到对应的Queue中,在绑定多个Queue到同一个Exchange的时候,这些Binding允许使用相同的binding key。binding key 并不是在所有情况下都生效,它依赖于Exchange Type,比如fanout类型的Exchange就会无视binding key,而是将消息路由到所有绑定到该Exchange的Queue。
五、RabbitMQ群集(windows)
1、windows单机多实例集群建立
这里是windows中单机配置集群(两个节点)配置说明,主要步骤如下:
A、安装RabbitMQ,e.g. D:\rabbitmq_server-3.5.1
B、将安装目录下的sbin目录中的bat文件做一个拷贝(因为需要两个节点,当然需要两份),本文做法是:直接在复制的另一份bat文件也放到sbin下,记得重命名(因为该目录已经加入path,为了方便,),最后目录如下:
C、因为RabbitMQ默认节点是跟主机名相关的,当前我们需要模拟两个主机,就需要修改windows的主机配置文件:hosts文件——C:\Windows\System32\drivers\etc\hosts,自定义两个虚拟域名,此处定义为下图形式:
D、修改相关的bat文件,主要是rabbitmq-server-cluster*与rabbitmqctl-cluster*文件(这两个文件是重命名过的),主要作用是为bat文件指定RABBITMQ_NODENAME、RABBITMQ_NODE_PORT、APPDATA、RABBITMQ_CONFIG_FILE(此处为了方便,其实后两个可以在需要的时候设置)
rabbitmq-server-cluster*的修改如下:
rabbitmq-server-cluster-1.bat(红色区域为添加的内容,路径可以自定义)
rabbitmq-server-cluster-2.bat
注意两个节点的nodename及port都不一样哦。
以下两个个修改是为了从命令行控制方便。
rabbitmqctl-cluster-1.bat
rabbitmqctl-cluster-2.bat
好了,文件修改完了,接下来可以开始建立集群的
E、进入命令行分别启动两个server
Cmd > : rabbitmq-server-cluster-1 ----启动第一个server
Cmd>: rabbitmq-server-cluser-2 ---启动第二个server
创建集群时需要先将一个server挂起,,这里我们选择第二个吧,
Rabbitmqctl-cluster-2 stop_app -----注意是stop_app 不是 stop
继续,加入节点:
Rabbitmqcl-cluster-2 join_cluster rabbit1@Cluster-Node1
激活node2
Rabbitmqctl-cluster-2 start_app
至此集群就建立好了,可以用rabbitmqcl-cluster-2 cluster_status命令查看集群状态
2、集群节点Web UI管理
1中集群建立起来了,如何通过web界面管理呢,做法如下:
A、说明:集群建立好后,只需要一个节点的管理插件起作用就可以管理其他节点。
前面的bat文件有两份,我们随便选择一个里面的插件bat作相关修改就可以了,这里选择:
Rabbitmq-plugins-cluster-1.bat,打开添加如下设置,根据自己先前的配置:
B、激活管理插件
Cmd>: rabbitmq-plugins-cluster-1 enable rabbitmq_management
这样node1的管理插件就激活了,注意该激活是建立在默认端口的——15672,访问:localhost:15672 即可。
3、HA与注意事项
1、 前面配置集群节点时修改了配置文件的位置,修改语句:
但,该配置路径中没有写文件的后缀,但实际真正的文件会带有.config,rabbitmq在查找文件时会自动添加后缀的。
确定配置文件有没有起作用(是否被rabbit找到或者配置项是否起作用)这一点可以在日志文件或者管理界面看到,此处由于没有找到配置文件,所以管理插件是默认的端口15672。
如果想让每个节点的管理插件在不同的端口监听需要在对应的节点的rabbitmq.config文件中配置插件的启动端口,针对本文档的两个节点配置截图如下(注意配置文件后缀):
节点1:
节点2:
其实修改一个节点,另一个使用默认端口也可以。
集群起来的时候节点的启动顺序问题,启动顺序不当会报错,由于次节点启动后会主动
1、 去连接主节点,主节点没起来时,次节点就会自己停掉,这是你会得到如下信息:
4、 高可用HA
A、RabbitMQ虽然支持集群但是普通的集群并不能保证高可用,具体原因如下:
在rabbitmq集群中,在一个节点中建立了队列,并且队列中有消息,此时,当有客户端消费时,该客户端可以连接任意一个集群中的节点,都可以拿到消息,其实背后是这样的:要取得消息都是通过队列所在的节点转发到客户端所连接的节点的,这也就意味着,客户端所连接的节点一旦挂掉,那么消息就不可用了。
B、为了解决上述问题,rabbitmq提供了队列镜像策略(queue mirrored),通过这种方式可以提升可用性与可靠性。
C、Rabbitmq的集群分为以下几种形式:
普通的集群:建立几个节点,并相互连接几个节点而构成。
高可用的集群:这种集群一般是通过镜像队列的形式,主要通过策略来配置,其中有
三种形式:all、exactly、nodes 。
All:mirror to all nodes in the cluster
Exactly:mirror to a set number of nodes
nodes :mirror to an explicit list of nodes
If you choose one of the latter two, you mustalso set ha-params
D
、对于高可用的测试
测试如下:
Windows 8.1
单机下有两个节点:rabbit1@Cluster-Node1 、rabbit2@Cluster-Node2,二者构成了集群。
具体操作:在其中一个节点(node1)上建立队列,然后放入几条消息,接下来,将节点node1挂起(stop_app),然后再从另一节点去取消息,看能否取到;为了进一步测试可以将一个节点从集群中移除掉(先挂起,然后移除):
挂起:rabbitmqctl-cluster-1 stop_app
移除:rabbitmqctl-cluster-1 -nrabbit2@Cluster-Node2 forget_cluster_node rabbit1@Cluster-Node1
接着再去另一个节点取消息。
注意:一般一个rabbitmq集群中有一个磁盘节点就可以了,其他的可以都是ram形式,尽量将ram形式的节点暴露给客户端去连接。
六、常用命令摘录
Rabbitmq服务器的主要通过rabbitmqctl和rabbimq-plugins两个工具来管理,以下是一些常用功能。
1、服务器启动与关闭
启动:Rabbitmq-server–detacher
关闭:rabbimqctl stop
若单机有多个实例,则在rabbitmqctlh后加–n 指定名称
2、获取服务器状态信息:
服务器:Rabbitmqctlstatus
其他对象状态:queue、Binding、exchange、channel、connection
通用格式:rabbitmqctl list_对象名字复数形式
队列:rabbitmqctl list_queues
Exchange: rabbitmqctl list_exchanges
1、插件管理
激活:rabbitmq-pugins enable 插件名
卸载:rabbitmq-plugins disable 插件名
2、虚拟主机(virtual_host)
新建:rabbitmqctl add_host XXX
删除:rabbitmqctl delete_host XXX
3、用户管理
添加新用户:rabbitmqctl add_user XXX pwd
删除用户:rabbimqcl delete_user XXX
修改密码:rabbitmqctl change_password {username} {newpwd}
用户角色:rabbitmqctl set_user_tags {username} {tags}
**Tag可以为administrator, monitoring, management***