【openstack】openstack中的消息队列

openstack中的消息队列

1 openstack中消息队列的使用

nova中的每个组件都会连接消息服务器,一个组件可能是一个消息发送者(如API、Scheduler),也可能是一个消息接收者(如compute、volume、network)。发送消息有两种方式:同步调用rpc.call和异步调用rpc.cast

openstack内部一些对象:

l Topic Publisher:该对象在进行rpc.call或rpc.cast时创建,每个对象都会连接同一个topic类型的交换器,消息发送完毕后对象被回收。

l Direct Publisher:该对象在进行rpc.call调用时创建,用于向消息发送者返回响应。该对象会根据接收到的消息属性连接一个direct类型的交换器。

l Direct Consumer:该对象在进行rpc.call调用时创建,用于接收响应消息。每一个对象都会通过一个的队列连接一个direct类型的交换器(队列和交换器以UUID命名)。

l Topic Consumer:该对象在内部服务初始化时创建,在服务过程中一直存在。用于从队列中接收消息,调用消息属性中指定的函数。该对象通过一个共享队列或一个私有队列连接一个topic类型的交换器。每一个内部服务都有两个topic consumer,一个用于rpc.cast调用(此时连接的是binding-key为“topic”的共享队列);另一个用于rpc.call调用(此时连接的是binding-key为“topic.host”的私有队列)

l Topic Exchange:topic类型交换器,每一个消息代理节点只有一个topic类型的交换器。

l Direct Exchange:direct类型的交换器,存在于rpc.call调用过程中,对于每一个rpc.call的调用,都会产生该对象的一个实例。

l Queue Element:消息队列。可以共享也可以私有。routing-key为“topic”的队列会在相同类型的服务中共享(如多个compute节点共享一个routing-key为“topic”的队列)。

各个对象的工作模型:

openstack中默认使用kombu(实现AMQP协议的Python函数库)连接RabbitMQ服务器。消息的收/发者都需要一个Connetion对象连接RabbitMQ服务器。

2 消息队列性能影响因素

消息队列在openstack整个架构中扮演着至关重要(交通枢纽)的作用,正是因为openstack部署的灵活性、模块的松耦合、架构的扁平化,反而使openstack更加依赖于消息队列(不一定使用RabbitMQ,可以是其他的消息队列产品),所以消息队列收发消息的性能和消息队列的HA能力直接影响openstack的性能。

在openstack中的任意时间点,影响消息服务器性能的的因素如下:

l 在rpc.call调用过程中:rpc.call的调用数决定了direct类型的交换器个数,相关的私有队列个数以及监听私有队列的direct consumer的个数。

l 工作者线程(内部服务)个数:相同属性的工作者线程(如compute节点)会共享一个队列,但每一个工作者线程都有一个私有队列。相同属性的工作者线程个数也决定了在topic类型交换器上的routing key的个数。

在实验环境下,主机名为kong,openstack各个组件启动后,会创建:

Ø Exchanges

1. nova (topic exchange)

Ø Queues

1. compute.kong

2. compute

3. network.kong

4. network

5. volume.kong

6. volume

7. scheduler.kong

8. scheduler

使用消息队列时有如下几个(Consumer类)属性:

Ø Durable:该属性决定了交换器和队列是否持久化,如持久化,则交换器和队列在RabbitMQ服务重启后仍然继续工作,否则交换器和队列的信息被清空。AMQP协议规定,持久化的队列只能绑定到持久化的交换器。

Ø Auto_delete:如果设置,则当所有队列结束后,交换器自动删除。默认为False。

Ø Exclusive:队列是否私有,如果该属性设置,则Auto_delete属性会自动生效。默认为False。

Ø Auto_ack:收到消息时是否自动发送回执。默认是False,要求消息接收者手动处理回执。

Ø No_ack:如果设置会提高性能,但会降低可靠性。

Ø Delivery_mode:消息的传输类型。目前RabbitMQ支持两种类型:

n 1或者“transient”:消息存储在内存,当服务器宕机或重启时消息丢失

n 2或者“persistent”:消息会同时在内存和硬盘保存,服务器宕机或重启时消息不丢失

默认为2。

在大规模部署的情况下,势必会对单节点的RabbitMQ server造成较大的负载,一旦发生单节点故障,整个openstack服务都会瘫痪。所以,部署时可以考虑使用RabbitMQ的HA等高级部署特性,具体参见RabbitMQ相关文档,在此不再赘述。

3 代码验证

3.1 服务的启动

根据以上分析可知,nova组件服务启动时会创建TopicConsumer,以“nova-compute”服务启动为例,在服务的启动过程中,会调用service::start()方法,在该方法中:

3.1.1 conn是什么?

是nova.openstack.common.amqp.ConnectionContext对象,这个对象是由RPC实现类调用create_connection()方法创建。RPC在openstack中有四种实现:

具体使用哪一种根据配置文件确定,默认的配置项是:

rpc_backend=nova.rpc.impl_kombu

ConnectionContext对象包含两个字段:

ü connection_pool:一个Connection对象池(继承自eventlet.pools.Pool),用于生成Connection对象。

ü connection:由connection_pool 生成。nova.openstack.common.rpc.impl_komku.Connection对象。该对象在初始化时,会根据配置的参数和策略连接RabbitMQ服务器。

3.1.2 rpc_dispatcher是什么?

RpcDispatcher对象。该对象中有属性callbacks,是一个包含ComputeManager对象的列表。用于接收到消息之后的处理。

3.1.3 三个create_consumer方法干了什么?

以第一个为例,在该函数中,创建了TopicConsumer对象。

3.1.4 consume_in_thread方法

在方法的实现里,又借助了evlentlet库创建超线程。在超线程主函数中调用了TopicConsumer对象的consume()方法(该类没有实现该方法,直接调用父类)。



对消息的处理包括:从消息中获取接口名称、获取接口参数、调用ComputeManager对象相应方法。

至此,“nova-compute”服务启动完成。

3.2 消息的发送

以创建虚拟机为例,由前几篇文章可知,经过Scheduler模块的过滤后,将创建虚拟机消息发送到对应的compute节点。



cast_to_compute_host
方法的实现:



rpc.cast最终会创建一个TopicPublisher对象,并调用该对象的send方法。



由上可知,
TopicConsumer对象会向名为“nova”的exchange上, 以 “compute.host”为routing-key发送消息。此时消息会发送到在名为“compute.host”队列上监听的TopicConsumer对象。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值