参考
http://dl528888.blog.51cto.com/2382721/1864895
http://kaibinyuan.blog.51cto.com/7304008/1610110
原因:
最近有一个异步需要使用消息队列,或许最终会选择阿里的rocketmq
性能
单台TPS基本上是在2000-3000左右
最新rabbitmq版本是3.6.2
yum安装
配置文件
RPM- /etc/rabbitmq/
http://www.cnblogs.com/stormli/p/rabbitmq.html
Broker:简单来说就是消息队列服务器实体。
Exchange:消息交换机,它指定消息按什么规则,路由到哪个队列。
Queue:消息队列载体,每个消息都会被投入到一个或多个队列。
Binding:绑定,它的作用就是把exchange和queue按照路由规则绑定起来。
Routing Key:路由关键字,exchange根据这个关键字进行消息投递。
vhost:虚拟主机,一个broker里可以开设多个vhost,用作不同用户的权限分离。
producer:消息生产者,就是投递消息的程序。
consumer:消息消费者,就是接受消息的程序。
channel:消息通道,在客户端的每个连接里,可建立多个channel,每个channel代表一个会话任务
http://blog.csdn.net/u013142781/article/details/50487028
AMQP当中有四个概念非常重要:虚拟主机(virtual host),交换机(exchange),队列(queue)和绑定(binding)。一个虚拟主机持有一组交换机、队列和绑定。为什么需要多个虚拟主机呢?很简单,RabbitMQ当中,用户只能在虚拟主机的粒度进行权限控制。因此,如果需要禁止A组访问B组的交换机/队列/绑定,必须为A和B分别创建一个虚拟主机。每一个RabbitMQ服务器都有一个默认的虚拟主机“/”。如果这就够了,那现在就可以开始了。
通过 Erlang 的分布式特性(通过 magic cookie 认证节点)进行 RabbitMQ 集群,各 RabbitMQ 服务为对等节点,即每个节点都提供服务给客户端连接,进行消息发送与接收。
这些节点通过 RabbitMQ HA 队列(镜像队列)进行消息队列结构复制。本方案中搭建 3 个节点,并且都是磁盘节点(所有节点状态保持一致,节点完全对等),只要有任何一个节点能够工作,RabbitMQ 集群对外就能提供服务。
Rabbitmq系统架构
RabbitMQ Server: 也叫broker server,是一种传输服务,负责维护一条从Producer到consumer的路线,保证数据能够按照指定的方式进行传输。
Producer,数据的发送方。
Consumer,数据的接收方。
Exchanges 接收消息,转发消息到绑定的队列。主要使用3种类型:direct, topic, fanout。
Queue RabbitMQ内部存储消息的对象。相同属性的queue可以重复定义,但只有第一次定义的有效。
Bindings 绑定Exchanges和Queue之间的路由。
Connection: 就是一个TCP的连接。Producer和consumer都是通过TCP连接到RabbitMQ Server的。
Channel:虚拟连接。它建立在上述的TCP连接中。数据流动都是在Channel中进行的。也就是说,一般情况是程序起始建立TCP连接,第二步就是建立这个Channel。
2.源码安装
红色标记必须做
yum remove rabbitmq-server -y
yum -y install erlang
yum -y install gcc gcc-c++ ncurses-devel
wget http://www.erlang.org/download/otp_src_R16B01.tar.gz
tar xvf otp_src_R16B01.tar.gz
cd otp_src_R16B01
./configure && make && make install
wget http://www.rabbitmq.com/releases/rabbitmq-server/v3.5.1/rabbitmq-server-generic-unix-3.5.1.tar.gz
tar zxvf rabbitmq-server-generic-unix-3.5.1.tar.gz
#ln -svf /usr/local/src/rabbitmq_server-3.4.3 /usr/local/rabbitmq-node1
#mkdir -p /usr/local/rabbitmq-node1
cd /opt/soft && mv rabbitmq_server-3.5.1 /usr/local
cd /usr/local && mv rabbitmq_server-3.5.1 rabbitmq-node1
mv rabbitmq_server-3.5.1 /opt/local/rabbitmq
vim ~/.bash_profile
PATH=/opt/mysql/bin:$PATH:$HOME/bin:/usr/lib/rabbitmq/bin/:/usr/local/rabbitmq-node1/sbin/:$PATH
source ~/.bash_profile
启用web插件
#rabbitmq-plugins enable rabbitmq_management #启用
关闭web插件
# rabbitmq-plugins disable rabbitmq_management
rabbitmq-plugins enable rabbitmq_management
rabbitmq-plugins list
rabbitmqctl stop
rabbitmq-server -detached
rabbitmqctl cluster_status
scp -P 8022 .erlang.cookie root@192.168.3.120:/root/
ps -ef | grep rabbitmq | grep -v "grep"
kill -9 54239
rabbitmqctl join_cluster rabbit@rabbitmq-test2
rabbitmqctl stop_app
rabbitmqctl start_app
rabbitmqctl change_password guest kaibin
cat /usr/local/rabbitmq-node2/ebin/rabbit.app | grep loopback --color
{loopback_users,[<<"">>]},
(虽然可以以比较猥琐的方式:将ebin目录下rabbit.app中loopback_users里的<<"guest">>删除,或者在配置文件rabbitmq.config中对该项进行配置,
https://my.oschina.net/hncscwc/blog/262246
并重启rabbitmq,可通过任意IP使用guest账号登陆管理控制台
http://kaibinyuan.blog.51cto.com/7304008/1610110
处于安全的考虑,guest这个默认的用户只能通过localhost来登录,其他的IP无法直接使用这个账号为了解决这个问题,需要在rabbitmq的配置文件中将loopback_users配置设置为空
http://dwf07223.blog.51cto.com/8712758/1547226
解决RabbitMQ远程不能访问的问题
注意:rabbitmq从3.3.0开始禁止使用guest/guest权限通过除localhost外的访问。
如果想使用guest/guest通过远程机器访问,需要在rabbitmq配置文件中(/etc/rabbitmq/rabbitmq.config)中设置loopback_users为[]。
/etc/rabbitmq/rabbitmq.config文件完整内容如下(注意后面的半角句号):
[{rabbit, [{loopback_users, []}]}].
rabbitmq的web管理界面默认guest:guest,这样的话,不是很安全,需要更改下
[root@rabbitmq-test1 ~]# rabbitmqctl change_password guest kaibin
Changing password for user "guest" ...
...done.
)
设计镜像队列策略
rabbitmqctl set_policy ha-all '^(?!amq\.).*' '{"ha-mode": "all"}'
#rabbitmqctl set_policy ha-all "^" '{"ha-mode":"all"}'
#沿用3.2的环境,现在我们把名为“hello”的队列设置为同步给所有节点
#rabbitmqctl set_policy ha-all “hello” ‘{“ha-mode”:”all”}’
ha-all 是同步模式,指同步给所有节点,还有另外两种模式ha-exactly表示在指定个数的节点上进行镜像,节点的个数由ha-params指定,ha-nodes表示在指定的节点上进行镜像,节点名称通过ha-params指定;
hello 是同步的队列名,可以用正则表达式匹配;
{“ha-mode”:”all”} 表示同步给所有,同步模式的不同,此参数也不同。
执行上面命令后,可以在web管理界面查看queue 页面,里面hello队列的node节点后会出现+2标签,表示有2个从节点,而主节点则是当前显示的node(xf7021是测试用的名字,按4-2应该为rabbitmq(1-3))。
镜像模式:消息实体会主动在各节点之间同步,而不是在消费者获取时才同步。降低系统性能消耗带宽
设置ha模式
rabbitmqctl set_policy [-p <vhostpath>] [--priority <priority>] [--apply-to <apply-to>] <name> <pattern> <definition>
name 策略名称
pattern 正则表达式,用来匹配资源,符合的就会应用设置的策略
definition 是json格式设置的策略。
apply-to 表示策略应用到什么类型的地方,一般有queues,exchange和all,默认是all
priority 是个整数优先级
其中ha-mode有三种模式:
all: 同步至所有的.
exactly: 同步最多N个机器. 当现有集群机器数小于N时,同步所有,大于等于N时则不进行同步. N需要额外通过ha-params来指定.
nodes: 只同步至符合指定名称的nodes. N需要额外通过ha-params来指定.# 这里设置的是同步全部的queue, 可以按需自己选择指定的queue
rabbitmqctl set_policy ha-all '.*' '{"ha-mode":"all"}'
线上操作
rabbitmq有主从之分,谁先启动,就是主
rabbitmq-server -detached
rabbitmqctl cluster_status
不需要再rabbitmqctl start_app
命令详细介绍
https://my.oschina.net/guol/blog/186445
stop_app
#停止erlang node上的rabbitmq的应用,但是erlang node还是会继续运行的
要在生产上使用,以下几点,有几点有可能用的上
注意的地方:
0.修改集群cluster_node_type
[root@rabbitmq-test1 rabbitmq]# rabbitmqctl stop_app
Stopping node 'rabbit@rabbitmq-test1' ...
...done.
[root@rabbitmq-test1 rabbitmq]# rabbitmqctl change_cluster_node_type ram
Turning 'rabbit@rabbitmq-test1' into a ram node ...
...done.
[root@rabbitmq-test1 ~]# rabbitmqctl cluster_status
Cluster status of node 'rabbit@rabbitmq-test1' ...
[{nodes,[{disc,['rabbit@rabbitmq-test2']},{ram,['rabbit@rabbitmq-test1']}]},
{running_nodes,['rabbit@rabbitmq-test2','rabbit@rabbitmq-test1']},
{partitions,[]}]
...done.
关于节点类型(ram |disk)
ram节点的状态保存在内存中,disk节点保存在磁盘中被加入的节点为disk,如本例中rabbit@host2为ram节点,rabbit@host1,rabbit@host3为ram节点,可以通过rabbitmqctl cluster命令改变加入的集群以及节点类型该命令后可以加多个节点名称,指定的节点就会变成disk节点
1.[root@rabbitmq-node1 ~]# cat /etc/rabbitmq/rabbitmq-env.conf
RABBITMQ_MNESIA_BASE=/var/lib/rabbitmq///需要使用的MNESIA数据库的路径
RABBITMQ_LOG_BASE=/var/log/rabbitmq///log的路径
RABBITMQ_PLUGINS_DIR=/usr/lib/rabbitmq/lib/rabbitmq_server-2.8.6/plugins//插件的路径
2.自动配置集群
vi /etc/rabbitmq/rabbitmq.config
添加以下内容
[{rabbit,
[{cluster_nodes, {['rabbit@r1', 'rabbit@r2'], disc}}]}].
之后启动集群
在r1和r2上执行
rabbitmq-server -detached
然后查看集群状态
rabbitmqctl cluster_status
3.高可用
安装并配置 HAProxy
在 192.168.1.4 上安装 HAProxy,然后修改 /etc/haproxy/haproxy.cfg:
listen rabbitmq_cluster 0.0.0.0:5672
mode tcp
balance roundrobin
server node1 192.168.1.1:5672 check inter 2000 rise 2 fall 3
server node2 192.168.1.2:5672 check inter 2000 rise 2 fall 3
server node2 192.168.1.3:5672 check inter 2000 rise 2 fall 3
4.用户与权限
在正式应用之前,我们先在RabbitMQ里创建一个vhost,加一个用户,并设置该用户的权限。使用rabbitmqctl客户端工具,在根目录下创建”/mq_test”这个vhost:
rabbitmqctl add_vhost /mq_test
创建一个用户名”test”,设置密码”test123″:
rabbitmqctl add_user test test123
设置pyh用户对/pyhtest这个vhost拥有全部权限:
rabbitmqctl set_permissions -p /mq_test test “.*” “.*” “.*”、
后面三个”*”代表pyh用户拥有对/pyhtest的配置、写、读全部权限
conn = amqp.Connection(host='localhost',userid='test',password='123456',ssl=False,virtual_host='test_host')
# rabbitmq-plugins enable rabbitmq_management
# rabbitmq-plugins list
# rabbitmqctl add_user admin admin
# rabbitmqctl set_user_tags admin administrator
RABBITMQ创建帐户
如果是集群的话,只要在一台主机设置即可,其它会自动同步。
#rabbitmqctl add_user iom 123456 –iom为新建的用户,123456为密码
#rabbitmqctl set_user_tags iom administrator –将用户设置为管理员角色
#rabbitmqctl set_permissions -p / iom “.*” “.*” “.*”
–在 / 虚拟主机里设置iom用户配置权限,写权限,读权限。.*是正则表达式里用法。rabbitmq的权限是根据不同的虚拟主机(virtual hosts)配置的,同用户在不同的虚拟主机(virtual hosts)里可能不一样。
5.rabbit_hosts=192.168.8.180:5672,192.168.8.53:5672,192.168.8.87:5672
测试rabbitmq的haproxy下的lb
将之前的测试代码中的
mq_servers = ['10.22.129.57', '10.22.129.58', '10.22.129.59']
改成
mq_servers = ['10.22.129.53', '10.22.129.53', '10.22.129.53']
执行测试代码,发现三个消息均发送成功,然后即使手动关闭其中一台mq,消息依然发送成功,通过rabbitctl list_queues也依然可以看到消息是成功收到3条的.
至此,可以看到rabbitmq-server成功的解除了single-point状态。
6.使用service方式启动rabbitmq-server报错erlexec: HOME must be set
解决办法:
在启动脚本中使用export指定HOME变量
export HOME=/opt/data/rabbitmq/
7.最常用的命令
查看所有队列信息
[root@rabbitmq-test1 ~]# rabbitmqctl list_queues
Listing queues ...
...done.
清除所有队列
rabbitmqctl reset
8.关于端口
rabbimq 55672 15672 为监控插件端口
rabbitmq 5672为数据端口
9.一些特别应该注意的东西
§ cookie在所有节点上必须完全一样,同步时一定要注意。
§ erlang是通过主机名来连接服务,必须保证各个主机名之间可以ping通。可以通过编辑/etc/hosts来手工添加主机名和IP对应关系。如果主机名ping不通,rabbitmq服务启动会失败。
§ 如果queue是非持久化queue,则如果创建queue的那个节点失败,发送方和接收方可以创建同样的queue继续运作。但如果是持久化queue,则只能等创建queue的那个节点恢复后才能继续服务。
§ 在集群元数据有变动的时候需要有disk node在线,但是在节点加入或退出的时候所有的disk node必须全部在线。如果没有正确退出disk node,集群会认为这个节点当掉了,在这个节点恢复之前不要加入其它节点。