首页 » OpenStack系统架构设计实战 » OpenStack系统架构设计实战全文在线阅读

《OpenStack系统架构设计实战》2.7.2 消息队列(AMQP)

关灯直达底部

AMQP即Advanced Message Queuing Protocol,是一个提供统一消息服务的应用层标准高级消息队列协议,是应用层协议的一个开放标准,为面向消息的中间件而设计。基于此协议的客户端与消息中间件可传递消息,并不受客户端/中间件不同产品、不同开发语言等条件的限制。典型的AMQP的产品实现有RabbitMQ和Qpid。OpenStack广泛使用消息队列作为组件间通信的中间件。

消息队列协议规范AMQP定义了一种消息队列传输模型。AMQP的消息模型概念主要是两个组件:Exchange和Queue,如图2-6所示。X就是Exchange,条状的条是Queue,这两者都在Server端,又称作Broker,这部分由服务器实现。客户端通常有Producer和Consumer两种类型,Producer与Consumer通过TCP连接RabbitMQ,按照规范定义的信令交互协议,通过服务器发送或接收消息。

Client分为两种角色,一种是消息发送方,如图2-6中P所示(Provider,消息发送者);一种是消息接收方,如图2-6中C所示(Consumer,消息接收者)。Client所传递的消息需通过服务器进行转发。

图2-6 AMQP的消息模型示意

交换器(Exchange)是交换消息的实体,起到消息路由、过滤的作用。队列(Queue)是接收消息的实体,本质上是一个缓存消息的队列。绑定器(Bind)将交换器和队列连接起来,并且封装消息的路由信息。

交换器指向队列的黑色线——RoutingKey,可以将它简单地理解为一条连接交换器和队列的路线,交换器和队列都需要通过Channel来进行定义,而RoutingKey则只需要在绑定时取个名称就行了。

图2-6中左边的客户向右边的客户发送消息,流程如下:

1)获取Connection(客户端到MQ服务器的TCP链路)。

2)获取Channel(逻辑层的链路,基于Connection)。

3)定义交换器、队列。

4)使用一个RoutingKey将队列绑定到一个交换器上。

5)通过指定一个交换器和一个RoutingKey来将消息发送到对应的队列上。

6)接收方在接收时也是获取Connection,接着获取Channel,然后指定一个队列直接到它关心的队列上取消息,它对交换器、RoutingKey及如何绑定都不关心,到对应的队列上去取消息就行了。

一个客户发送消息,哪些Client可以收到消息,其核心就在于交换器、RoutingKey、队列的关系上。

交换器在定义的时候是有类型的,以决定到底是哪些队列符合条件,可以接收消息,OpenStack中使用的交换器类型主要有以下3种。

1)Fanout:所有绑定到此交换器的队列都可以接收消息。此为(publisher/subscriber)模式。

2)Direct:通过RoutingKey和交换器决定的那个唯一的队列可以接收消息,此为1对1模式。

3)Topic:所有符合RoutingKey(可以是一个表达式)的RoutingKey所绑定的队列可以接收消息,和扇出相比,这个相当于通过RoutingKey进行了过滤。

使用RoutingKey为#、交换器类型为topic的时候,相当于使用扇出。

以nova-api收到外部请求创建虚拟机为例。nova-api通过rpc.cast函数封装,通过消息队列发送消息给nova-scheduler,触发nova-scheduler来调度nova-compute创建虚拟机。

rpc.cast(context, FLAGS.scheduler_topic, {"method": "run_instance", "args": {"topic": FLAGS.compute_topic,"instance_id": instance_id,"availability_zone": availability_zone,"injected_files": injected_files}})

第二个参数即为调度器关心的topic,系统中设定的值为scheduler,表明该消息需要nova-scheduler来接收并处理;第三个参数是消息体,使用的是key/value值对,method对应的run_instance表明这是一条创建虚拟机的消息。第一个参数context是上下文通用环境,其他参数编入到args参数里传递给nova-scheduler。