Cinder组件简介
Openstack 的主要组件有 Nova、Cinder、Neutron、Glance 等,分别负责云平台的计算、存储、网络资源管理。OpenStack 各组件之间是通过 REST 接口进行相互通信,而各组件内部则采用了基于 AMQP 模型的 RPC 通信。下面以cinder组件为例,讲述RPC调用过程。
在讲述 OpenStack RPC 通信机制之前,首先介绍一下 cinder 系统架构,Cinder 主要由 3 个组件组成,cinder-api, cinder-scheduler 和 cinder-volume:
Cinder-api 是 cinder 服务的 endpoint,提供 rest 接口,负责处理 client 请求,并将 RPC 请求发送至 cinder-scheduler 组件。
Cinder-scheduler 负责 cinder 请求调度,其核心部分就是 scheduler_driver, 作为 scheduler manager 的 driver,负责 cinder-volume 具体的调度处理,发送 cinder RPC 请求到选择的 cinder-volume。
Cinder-volume 负责具体的 volume 请求处理,由不同后端存储提供 volume 存储空间。目前各大存储厂商已经积极地将存储产品的 driver 贡献到 cinder 社区。
Openstack RPC通信基础
Openstack 组件内部的 RPC(Remote Producer Call)机制的实现是基于 AMQP(Advanced Message Queuing Protocol)作为通讯模型,从而满足组件内部的松耦合性。AMQP 是用于异步消息通讯的消息中间件协议,AMQP 模型有四个重要的角色:
- Exchange:根据 Routing key 转发消息到对应的 Message Queue 中
- Routing key:用于 Exchange 判断哪些消息需要发送对应的 Message Queue
- Publisher:消息发送者,将消息发送的 Exchange 并指明 Routing Key,以便 Message Queue 可以正确的收到消息
- Consumer:消息接受者,从 Message Queue 获取消息
消息发布者 Publisher 将 Message 发送给 Exchange 并且说明 Routing Key。Exchange 负责根据 Message 的 - Routing Key 进行路由,将 Message 正确地转发给相应的 Message Queue。监听在 Message Queue 上的 Consumer 将会从 Queue 中读取消息。
Routing Key 是 Exchange 转发信息的依据,因此每个消息都有一个 Routing Key 表明可以接受消息的目的地址,而每个 Message Queue 都可以通过将自己想要接收的 Routing Key 告诉 Exchange 进行 binding,这样 Exchange 就可以将消息正确地转发给相应的 Message Queue。
AMQP 定义了三种类型的 Exchange,不同类型 Exchange 实现不同的 routing 算法:
- Direct Exchange:Point-to-Point 消息模式,消息点对点的通信模式,Direct Exchange 根据 Routing Key 进行精确匹配,只有对应的 Message Queue 会接受到消息
- Topic Exchange:Publish-Subscribe(Pub-sub)消息模式,Topic Exchange 根据 Routing Key 进行模式匹配,只要符合模式匹配的 Message Queue 都会收到消息
- Fanout Exchange:广播消息模式,Fanout Exchange 将消息转发到所有绑定的 Message Queue
OpenStack 目前支持的基于 AMQP 模型的 RPC backend 有 RabbitMQ、QPid、ZeroMQ,对应的具体实现模块在 cinder 项目下 Openstack/common/RPC/目录下,impl_*.py 分别为对应的不同 backend 的实现。
创建 volume 的 RPC 通信过程
Create volume 的过程可以看做是两个阶段的 RPC 请求处理,第一阶段:
- Client 即 cinder-api 调用 RPC.cast 发送消息,RPC.cast 创建 Topic Publisher 对象,topic 为 cinder-scheduler,也就是消息的 Routing Key,Exchange name 为 OpenStack,消息体中标记了消息接收者即 Server 所需要调用的方法“create_volume”;
- Exchange 接收到消息,根据 Routing Key 将消息发送至 Message Queue cinder-scheduler 上,这个 Message Queue 是由 cinder-scheduler 服务的 Topic Consumer 订阅的,因此,cinder-scheduler 服务将接收到 create_volume 的消息
- Consumer 调用注册的 RPC_dispatcher,即 cinder-scheduler manager,然后由 cinder-scheduler manager 调用 RPC 处理方法 create_volume
Create volume 请求的第二阶段由 cinder-scheduler 的 create_volume 方法调用发起,即 cinder-scheduler 使用 filter and weighing 算法选取了 cinder-volume 的 host 用于创建 volume,则调用 RPC.cast 请求向 host 发送 RPC 请求,这个阶段 cinder-scheduler 为请求发起者即 client,cinder-volume 为请求处理者即 server。
- Cinder-scheduler 调用 RPC.cast,Exchange name 为 Openstack, routing-key 为 cinder-volume:host
- Exchange 接收到消息,根据 Routing Key 将消息发送到队列 cinder-volume:host 上
- 在主机 host 上的 Cinder-volume consumer 从 Queue 中接收到 message,回调 RPC_dispatcher 即 cinder-volume manager
- Cinder-volume manger 根据消息体中 method 信息,调用 create_volume 方法,创建 volume
OpenStack Notification
OpenStack Notification 机制用于通知用户或者开发者当前请求执行状态,在 RPC 通信角色一节中介绍了 Notification Publisher,其实就是一种 Topic Publisher。
启用 Notification 机制,需要在 Cinder 配置文件中配置 notification_driver。
notification_driver = cinder.Openstack.common.notifier.RPC_notifier
Notification priority 提供了 DEBUG, WARN, INFO, ERROR, CRITICAL 五个级别的消息,Cinder 的 notification 的 Exchange name 是 Openstack,topic 是 notifications.priority,例如 notifications.info
Cinder 项目默认的 Exchange name 是 OpenStack,由于 Exchange 负责信息转发,因此能够看到所有流入 Exchange 的消息,如果我们仅想要查看 notification 类型的消息,也可以自己创建 Message Queue,使用 Routing key 绑定到 Exchange 上。
一种创建 Queue 的简单方法是使用 Qpid 提供的客户端工具 qpid-config。关于 qpid-config 工具的具体使用方法可以通过帮助文档来获取。
创建接受 notification INFO 级别的消息,则执行如下操作
创建 Message Queue
qpid-config add Queue notification_info
可以通过 qpid-tool 中使用 list Queue 查看已经创建了以 notification.info 为名的 Queue,这里仅仅是创建了 Message Queue
建立 Routing Key
qpid-config [OPTIONS] bind <Exchange-name> <Queue-name> [binding-key] qpid-config bind Openstack notification_info notifications.info
建立了 Exchange 和 Message Queue 之间的路由关系,Routing Key 为 notifications.info,只要 Exchange 接收到 Routing Key 为 notifications.info 的消息将会将消息转发至名字为 notification_info 的 Queue 中
查看 notifications.info 的消息
./drain -t 1000 notification_info
使用 cinder 命令创建一个 volume,则能够查看到 notifications.info 的消息内容了。