总的来说,rabbitmq使用erlang语言编写,其架构类似于servlet容器运行servlet应用,底层是erlang VM、然后是erlang节点,上面是应用。如下所示:
每个MQ中运行的应用可通过rabbitmqctl status看到,如下:
[root@iZbp112kwadw1qt8emked5Z logs]# rabbitmqctl status
Status of node rabbit@iZbp112kwadw1qt8emked5Z ...
[{pid,30445},
{running_applications,
[{rabbitmq_tracing,"RabbitMQ message logging / tracing","3.5.6"},
{rabbitmq_management,"RabbitMQ Management Console","3.5.6"},
{rabbitmq_management_agent,"RabbitMQ Management Agent","3.5.6"},
{rabbit,"RabbitMQ","3.5.6"},
{os_mon,"CPO CXC 138 46","2.2.7"},
{rabbitmq_web_dispatch,"RabbitMQ Web Dispatcher","3.5.6"},
{webmachine,"webmachine","1.10.3-rmq3.5.6-gite9359c7"},
{mochiweb,"MochiMedia Web Server","2.7.0-rmq3.5.6-git680dba8"},
{amqp_client,"RabbitMQ AMQP Client","3.5.6"},
{xmerl,"XML parser","1.2.10"},
{inets,"INETS CXC 138 49","5.7.1"},
{mnesia,"MNESIA CXC 138 12","4.5"},
{sasl,"SASL CXC 138 11","2.1.10"},
{stdlib,"ERTS CXC 138 10","1.17.5"},
{kernel,"ERTS CXC 138 10","2.14.5"}]},
各自的含义如下:
在集群模式下的时候,其结构如下:
从逻辑上讲,RabbitMQ集群是单一的message broker,消息队列消费者连接集群中的任一个节点都可以。如果使用典型的负载均衡机制比如LVS或者HAProxy,client只需要访问单一一个地址,由负载均衡器负责load balance,将访问请求分发给各个节点。
对于Queue来讲,虽然它的metadata在每个节点上都有,但只有在它被创建的那个RabbitMQ 节点上才具有完整的信息:比如state/contents等,这个node被称为此queue的owner node。其他节点只知道这个queue的metadata信息和一个指向queue的owner node的指针。
如果一个client访问RabbitMQ的节点上没有需要的queue的完整信息,RabbitMQ将根据这个指针将请求转发到owner node。如下:
如果这样的话,那万一主节点挂了,queue岂不是又但点了,rabbitmq自然是不会傻到这程度。所以一般来说,对于需要可信传递的消息,应该结合队列级别的mirror(具体是客户端建立queue的时候设置还是policy设置,仍然看具体的开发人员配备)。
参考:http://www.rabbitmq.com/ha.html。
http://www.cnblogs.com/flat_peach/archive/2013/04/07/3004008.html
http://www.rabbitmq.com/clustering.html
http://www.cnblogs.com/lion.net/p/5725474.html
https://www.rabbitmq.com/parameters.html#policies