OpenStack消息队列AMQP技术具体实现 [分析基于icehouse]

来源:互联网 发布:淘宝优惠劵 编辑:程序博客网 时间:2024/05/16 14:01


       本文系技术总结,供将来需要时翻开看看, 如有错误, 欢迎交流微笑

 第一部分:关键技术

       先发下感慨, 社区的code真是变化太快, code结构发生了很大的重构增强, 关于消息队列, openstack.common.rpc慢慢的都会转移到oslo.messaging上,以我2014年3月的code为例, 仅有heat, neutron, ceilometer没有转移。无论架构和部分实现如何变化,技术原理还是原来的原理。

       OpenStack中的消息队列技术使用的AMQP(Advanced Message Queue Protocol)异步消息处理机制。AMQP使用的是发布/订阅的模式, 它的好处是

       1)  实现消息发布方(服务器端)和消息处理方(客户端)的解耦和。

        2) 消息发布方和消息处理方可以是异步的

        3) 可以做到负载均衡。这个就涉及到消息队列中间件的实现问题, 当多个server端在运行, 请求就会被它们平衡到各个server端

        OpenStack支持RabiitMQ或者Qpid,也可以使用Zero MQ等等消息中间件,一般通过指定rpc_backend

rpc_backend = nova.openstack.common.rpc.impl_qpid #impl_qpid为qpid, impl_kommu为Rabbitmq,impl_zmq为Zero MQ, 当发现没有nova.openstack.common.rpc路径时不要惊讶, 主要是为了兼容havana与之前版本, icehouse的代码中对此路径进行了处理。

         本文以Qpid为例总结OpenStack中的消息队列技术,Qpid除了基本消息队列功能, 还有很多增强功能,实现高可用性, 如HA, ssl连接等.

         使用消息队列broker包含invoker和worker, invoker向消息队列中发消息, worker处理消息。在nova中api会通过rpcapi发出消息到消息队列,这是invoker端的工作, 而compute会收到消息, 通过它的Manager(也可以说为endpoint)处理消息[worker端], 如下图所示, 左边为invoker, 右侧为worker, invoker中发出消息的方式有两种, 一种是请求/响应模式 rpc.call; 另一种是广播模式rpc.cast

图1 以nova/compute目录下code为例, 讲述API与compute之间的消息发送过程

       

图2 oslo.messaging._drivers.impl_qpid.py中类结构

TopicPublisher: Topic消息发布, 也就是发布消息到消息队列, 是invoker工作内容, 无论是rpc.call还是rpc.cast这个都是有的

TopicConsumer:Topic消息处理, 从消息队列接收消息并处理,是worker工作内容,无论是rpc.call还是rpc.cast这个都是有的

DirectPublisher:这个是在rpc.call模式时, 当消息被TopicConsumer处理后, 为了给invoker以响应, 必须通过DirectPublisher发布direct消息到消息队列

DirectConsumer:仅当rpc.call调用时才会出现, 负责在invoker端接收消息队列中worker端发来的响应信息, 完成rpc.call整个流程

FanoutPublisher:这个就是所谓的fanout模式了, 一个消息被广播, 多个worker端都要接收此消息并处理, FanoutPublisher为invoker端

FanoutConsumer:这个就是fanout模式的处理端worker端了

NotifyPublisher:负责发出notification消息, notification listener将会处理这些消息


          下面几张图摘自http://docs.openstack.org/developer/nova/devref/rpc.html,它以api作为invoker, compute作为worker, 讲述了TopicPublisher、TopicConsumer、DirectPublisher、DirectConsumer的关系。

   

        图3 以RabbitMQ为例 阐述Publisher/Consumer关系

         解释一下,Exchange: 消息交换机, 指定消息按照什么规则, 路由到哪个queue;Queue:消息队列承载者

         图3中有两个Exchange,针对一个消息队列节点, 针对消息的type(topic或者direct, fault),每个type在一个消息中间件节点上,只能有一个Exchange。

         图4为rpc.call流程图,Invoker 端Topic Publisher发布消息如key为“topic.host”, 因为是rpc.call, 所以同时启动Direct Consumer侦听msg_id消息,消息发出后, Exchange就会根据消息, 路由相应的Queue, 监听此Queue的Worker端Topic Consumer就会收到消息, 并处理, 同时会开始给Invoker给与响应, 告知消息被处理,对应图4中的Direct Publisher发布消息msg_id到消息队列, Invoker端的Direct Consumer接收。

         图5为rpc.cast流程图,与rpc.call相比, 只是没有Direct Publisher和Direct Consumer来处理返回, 其他一样。

图4 rpc.call 流程


图5 rpc.cast流程

         

第二部分 OpenStack中rpc部分代码的实现

                本部分的实现基本都使用了oslo/messaging, 在另一文章oslo/messaging 说明


0 0
原创粉丝点击