RabbitMQ简介
AMQP,即Advanced Message Queuing Protocol,高级消息队列协议,是应用层协议的一个开放标准,为面向消息的中间件设计。消息中间件主要用于组件之间的解耦,消息的发送者无需知道消息使用者的存在,反之亦然。
AMQP的主要特征是面向消息、队列、路由(包括点对点和发布/订阅)、可靠性、安全。
RabbitMQ是一个开源的AMQP实现,服务器端用Erlang语言编写,支持多种客户端,如:Python、Ruby、.NET、Java、JMS、C、PHP、ActionScript、XMPP、STOMP等,支持AJAX。用于在分布式系统中存储转发消息,在易用性、扩展性、高可用性等方面表现不俗。
官网的配置
http://www.rabbitmq.com/production-checklist.html
http://www.rabbitmq.com/configure.html
http://www.rabbitmq.com/memory.html
http://www.rabbitmq.com/production-checklist.html#resource-limits-ram
参考文档
http://www.cnblogs.com/crazylqy/p/6567253.html
http://wangqingpei557.blog.51cto.com/1009349/1881540
基本概念
ConnectionFactory、Connection、Channel
ConnectionFactory、Connection、Channel都是RabbitMQ对外提供的API中最基本的对象。Connection是RabbitMQ的socket链接,它封装了socket协议相关部分逻辑。ConnectionFactory为Connection的制造工厂。
Channel是我们与RabbitMQ打交道的最重要的一个接口,我们大部分的业务操作是在Channel这个接口中完成的,包括定义Queue、定义Exchange、绑定Queue与Exchange、发布消息等。
Queue
Queue(队列)是RabbitMQ的内部对象,用于存储消息,。
RabbitMQ中的消息都只能存储在Queue中,生产者生产消息并最终投递到Queue中,消费者可以从Queue中获取消息并消费。
多个消费者可以订阅同一个Queue,这时Queue中的消息会被平均分摊给多个消费者进行处理,而不是每个消费者都收到所有的消息并处理。
Message acknowledgment
在实际应用中,可能会发生消费者收到Queue中的消息,但没有处理完成就宕机(或出现其他意外)的情况,这种情况下就可能会导致消息丢失。为了避免这种情况发生,我们可以要求消费者在消费完消息后发送一个回执给RabbitMQ,RabbitMQ收到消息回执(Message acknowledgment)后才将该消息从Queue中移除;如果RabbitMQ没有收到回执并检测到消费者的RabbitMQ连接断开,则RabbitMQ会将该消息发送给其他消费者(如果存在多个消费者)进行处理。这里不存在timeout概念,一个消费者处理消息时间再长也不会导致该消息被发送给其他消费者,除非它的RabbitMQ连接断开。
这里会产生另外一个问题,如果我们的开发人员在处理完业务逻辑后,忘记发送回执给RabbitMQ,这将会导致严重的bug——Queue中堆积的消息会越来越多;消费者重启后会重复消费这些消息并重复执行业务逻辑…
另外pub message是没有ack的。
Message durability
如果我们希望即使在RabbitMQ服务重启的情况下,也不会丢失消息,我们可以将Queue与Message都设置为可持久化的(durable),这样可以保证绝大部分情况下我们的RabbitMQ消息不会丢失。但依然解决不了小概率丢失事件的发生(比如RabbitMQ服务器已经接收到生产者的消息,但还没来得及持久化该消息时RabbitMQ服务器就断电了),如果我们需要对这种小概率事件也要管理起来,那么我们要用到事务。
Prefetch count
前面我们讲到如果有多个消费者同时订阅同一个Queue中的消息,Queue中的消息会被平摊给多个消费者。这时如果每个消息的处理时间不同,就有可能会导致某些消费者一直在忙,而另外一些消费者很快就处理完手头工作并一直空闲的情况。我们可以通过设置prefetchCount来限制Queue每次发送给每个消费者的消息数,比如我们设置prefetchCount=1,则Queue每次给每个消费者发送一条消息;消费者处理完这条消息后Queue会再给该消费者发送一条消息。
Exchange
在上一节我们看到生产者将消息投递到Queue中,实际上这在RabbitMQ中这种事情永远都不会发生。实际的情况是,生产者将消息发送到Exchange,由Exchange将消息路由到一个或多个Queue中(或者丢弃)。
Exchange是按照什么逻辑将消息路由到Queue的?这个将在Binding一节介绍。
RabbitMQ中的Exchange有四种类型,不同的类型有着不同的路由策略,这将在Exchange Types一节介绍。
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了。
1.安装erlang
下载rpm仓库:wget http://packages.erlang-solutions.com/erlang-solutions-1.0-1.noarch.rpm
安装rpm仓库
rpm -Uvh erlang-solutions-1.0-1.noarch.rpm
安装erlang
yum -y install erlang
2,安装rabbitmq
wget https://github.com/rabbitmq/rabbitmq-server/releases/download/rabbitmq_v3_6_11/rabbitmq-server-3.6.11-1.el6.noarch.rpm
rpm --import https://www.rabbitmq.com/rabbitmq-release-signing-key.asc
yum install rabbitmq-server-3.6.11-1.noarch.rpm
yum install rabbitmq-server-3.6.11-1.el6.noarch.rpm
Installed:
rabbitmq-server.noarch 0:3.6.11-1.el6
Dependency Installed:
socat.x86_64 0:1.7.2.3-1.el6
3,启动
mkdir -p /data/rabbitmq/data
mkdir -p /data/rabbitmq/log
chown rabbitmq:rabbitmq /data/rabbitmq/ -R
/etc/init.d/rabbitmq-server restart
4,添加帐号
rabbitmqctl add_user rabbitmq76 RMQXXXXXXXXX
rabbitmqctl set_user_tags rabbitmq76 administrator
rabbitmqctl set_permissions -p / rabbitmq76 ".*" ".*" ".*"
5,加入集群
[[email protected] etc]# cat /etc/hosts
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
192.168.188.76 rabbitmq76
192.168.188.77 rabbitmq77
192.168.188.78 rabbitmq78
192.168.188.79 rabbitmq79
192.168.188.80 rabbitmq80
scp -P10001 .erlang.cookie 192.168.188.77:$PWD
scp -P10001 .erlang.cookie 192.168.188.78:$PWD
scp -P10001 .erlang.cookie 192.168.188.79:$PWD
scp -P10001 .erlang.cookie 192.168.188.80:$PWD
[[email protected] ~]# rabbitmqctl stop_app
Stopping rabbit application on node [email protected]
[[email protected] ~]# rabbitmqctl join_cluster [email protected]
Clustering node [email protected] with [email protected]
[[email protected] ~]# rabbitmqctl start_app
Starting node [email protected]
rabbitmq-plugins enable rabbitmq_management
[[email protected] etc]# rabbitmq-plugins list|wc -l
32
[[email protected] etc]# rabbitmqctl cluster_status
Cluster status of node [email protected]
[{nodes,[{disc,[[email protected],[email protected],[email protected],
[email protected],[email protected]]}]},
{running_nodes,[[email protected],[email protected],[email protected],
[email protected],[email protected]]},
{cluster_name,<<"[email protected]">>},
{partitions,[]},
{alarms,[{[email protected],[]},
{[email protected],[]},
{[email protected],[]},
{[email protected],[]},
{[email protected],[]}]}]
6,设置镜像队列策略
可以参考
http://blog.csdn.net/zheng911209/article/details/49949303
在任意一个节点上执行下面的命令
rabbitmqctl set_policy ha-all "^" ‘{"ha-mode":"all"}‘
剩下的可以在web上操作
1),首先创建vhost,例如yicheapp
2),其次创建user,例如yichapp,tags设置None,vhosts选择yicheapp ,设置好密码
3),配置police
选择要应用策略的vhost
name:起个有意义的名称,比如我们写的ha-all(表示在所有节点建立镜像)
pattern:为正则表达式,是要匹配的exchange和queue的名称,比要匹配所有exchange或者queue的话,可以直接写 ‘^‘,表示任意名称开头的,如果要指定以ha-开发的exchange和queue的话
可以使用 ‘^ha-‘
applyto:是表示策略应用的范围,比如 exchange或者queue还是两者都应用。
priority:优先级,是只在exchange转发时优先级高的会优先转发。
definition: 下面有提示,点击就可以definition的定义表单上去,值的话,点击下面定义后面跟的?号就可以看到可选值。通常会加两项定义:
ha-mode:all 在集群所有节点中创建镜像exchange或者queue
ha-sync-mode:automatic 自动同步到镜像节点
4),创建exchange,例如yicheapp-exchange
5),配置queues,例如yicheapp-queues
6),绑定exchange与queues,例如yicheapp-exchange和yicheapp-queues.key绑定
7,优化配置等
官网的配置
http://www.rabbitmq.com/production-checklist.html
http://www.rabbitmq.com/configure.html
http://www.rabbitmq.com/memory.html
http://www.rabbitmq.com/production-checklist.html#resource-limits-ram
线上优化后配置
[[email protected] rabbitmq]# cat rabbitmq.conf
[
{rabbit,
[
{loopback_users, []},
{vm_memory_high_watermark, 0.40}, #最大使用内存40%,erlang开始GC
{vm_memory_high_watermark_paging_ratio, 0.8}, #32G内存,32*0.8*0.2时开始持久化磁盘
{disk_free_limit, "10GB"}, #磁盘使用量剩余10G时,不收发消息
{hipe_compile, true}, #开启hipe,提高erlang性能
{collect_statistics_interval, 10000}, #统计刷新时间默认5秒,改成10秒
{cluster_partition_handling, autoheal} #网络优化参数,不稳定时用这个选项
]
}
].
[[email protected] rabbitmq]# cat rabbitmq-env.conf
[email protected] #节点名字,全局唯一
RABBITMQ_MNESIA_BASE=/data/rabbitmq/data #消息落地存放位置
RABBITMQ_LOG_BASE=/data/rabbitmq/log #日志位置
RABBITMQ_SERVER_ADDITIONAL_ERL_ARGS="+A 128" #默认65,server线程
另外系统参数需要留有swap空间,及打开文件数rabbitmq启动进程至少需要5万,yum安装时rabbitmq启动,源码安装时root启动
[[email protected] rabbitmq]# cat /etc/security/limits.conf
* soft nofile 65536
* hard nofile 131072
* soft nproc 10240
* hard nproc 20480
备注
内存控制:
vm_memory_high_watermark 该值为内存阈值,默认为0.4。意思为物理内存的40%。40%的内存并不是内存的最大的限制,它是一个发布的节制,当达到40%时Erlang会做GC。最坏的情况是使用
内存80%。如果把该值配置为0,将关闭所有的publishing 。
rabbitmqctl set_vm_memory_high_watermark 0
Paging 内存阈值,该值为默认为0.5,该值为vm_memory_high_watermark的20%时,将把内存数据写到磁盘。
如机器内存16G,当RABBITMQ占用内存1.28G(16*0.4*0.2)时把内存数据放到磁盘。
硬盘控制:
当RabbitMQ的磁盘空闲空间小于50M(默认),生产者将被BLOCK,
如果采用集群模式,磁盘节点空闲空间小于50M将导致其他节点的生产者都被block
可以通过disk_free_limit来对进行配置。
Memory
By default, RabbitMQ will not accept any new messages when it detects that it‘s using more than 40% of the available memory (as reported by the OS):
{vm_memory_high_watermark, 0.4}. This is a safe default and care should be taken when modifying this value, even when the host is a dedicated RabbitMQ node.
The OS and file system use system memory to speed up operations for all system processes. Failing to leave enough free system memory for this purpose will have an
adverse effect on system performance due to OS swapping, and can even result in RabbitMQ process termination.
A few recommendations when adjusting the default vm_memory_high_watermark:
Nodes hosting RabbitMQ should have at least 128MB of memory available at all times.
The recommended vm_memory_high_watermark range is 0.40 to 0.66
Values above 0.7 are not recommended. The OS and file system must be left with at least 30% of the memory, otherwise performance may degrade severely due to paging.
As with every tuning, benchmarking and measuring are required to find the best setting for your environment and workload.
Disk Space
The current 50MB disk_free_limit default works very well for development and tutorials. Production deployments require a much greater safety margin. Insufficient disk
space will lead to node failures and may result in data loss as all disk writes will fail.
Why is the default 50MB then? Development environments sometimes use really small partitions to host /var/lib, for example, which means nodes go into resource alarm
state right after booting. The very low default ensures that RabbitMQ works out of the box for everyone. As for production deployments, we recommend the following:
{disk_free_limit, {mem_relative, 1.0}} is the minimum recommended value and it translates to the total amount of memory available. For example, on a host dedicated to
RabbitMQ with 4GB of system memory, if available disk space drops below 4GB, all publishers will be blocked and no new messages will be accepted. Queues will need to
be drained, normally by consumers, before publishing will be allowed to resume.
{disk_free_limit, {mem_relative, 1.5}} is a safer production value. On a RabbitMQ node with 4GB of memory, if available disk space drops below 6GB, all new messages
will be blocked until the disk alarm clears. If RabbitMQ needs to flush to disk 4GB worth of data, as can sometimes be the case during shutdown, there will be
sufficient disk space available for RabbitMQ to start again. In this specific example, RabbitMQ will start and immediately block all publishers since 2GB is well under
the required 6GB.
{disk_free_limit, {mem_relative, 2.0}} is the most conservative production value, we cannot think of any reason to use anything higher.If you want full confidence in
RabbitMQ having all the disk space that it needs, at all times, this is the value to use.
Open File Handles Limit
Operating systems limit maximum number of concurrently open file handles, which includes network sockets. Make sure that you have limits set high enough to allow for
expected number of concurrent connections and queues.
Make sure your environment allows for at least 50K open file descriptors for effective RabbitMQ user, including in development environments.
As a rule of thumb, multiple the 95th percentile number of concurrent connections by 2 and add total number of queues to calculate recommended open file handle limit.
Values as high as 500K are not inadequate and won‘t consume a lot of hardware resources, and therefore are recommended for production setups. See Networking guide for
more information.