OpenStack oslo.messaging使用

本文深入讲解了RPC通信机制的关键组成部分,包括Transport层的功能与实现、Target的定义与用途、Endpoint和Server的概念及其交互方式,同时介绍了RPCClient的使用方法及NotificationListener与Notifier的工作原理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

基础知识:

    参考博客:http://blog.youkuaiyun.com/happyAnger6/article/details/54777429

   

  •   Transport

  Transport(传输层)主要实现RPC底层的通信(比如socket)以及事件循环,多线程等其他功能.可以通过URL来获得不同transport的句柄.URL的格式为:

transport://user:password@host:port[,hostN:portN]/virtual_host

  目前支持的Transport有rabbit,qpid与zmq,分别对应不同的后端消息总线.用户可以使用oslo.messaging.get_transport函数来获得transport对象实例的句柄.


  • Target

Target封装了指定某一个消息最终目的地的所有信息


  • Endpoint

    Endpoint包含一组方法,这组方法是可以被客户端远程调用的.


  • Server

    一个RPC服务器可以暴露多个endpoint,每个endpoint包含一组方法,这组方法是可以被客户端通过某种Transport对象远程调用的.创建Server对象时,需要指定Transport,Target和一组endpoint.


  • RPC Client
    通过RPC Client,可以远程调用RPC Sever上的方法.远程调用时,需要提供一个字典对象来指明调用的上下文,调用方法的名字和传递给调用方法的参数(用字典表示).
    有cast和call两种远程调用方式.通过cast方式远程调用,请求发送后就直接返回了;通过call方式调用,需要等响应从服务器返回.

RPC-server和PRC-client举例

rpc_server.py

from oslo_config import cfg
import oslo_messaging as messaging
from oslo_messaging.rpc import dispatcher

class ServerControlEndpoint(object):
    target = messaging.Target(namespace='control',
                              version='2.0')

    def __init__(self, server):
        self.server = server

    def stop(self, ctx):
        print "------ServerControlEndpoint. stop --------"
        if self.server:
            self.server.stop()
        return "stop return"

class TestEndpoint(object):
    def test(self, ctx, arg):
        print "------ TestEndpoint.test --------"
        print "arg:", arg
        return arg


transport = messaging.get_transport(cfg.CONF)
target = messaging.Target(topic='test',
                          server='server1')
endpoints = [
    ServerControlEndpoint(None),
    TestEndpoint(),
]

access_policy = dispatcher.DefaultRPCAccessPolicy

server = messaging.get_rpc_server(transport, target, endpoints,
                                  executor='threading',
                                  access_policy=access_policy)
server.start()
server.wait()           


rpc_client.py

from oslo_config import cfg
import oslo_messaging as messaging

transport = messaging.get_transport(cfg.CONF)
target = messaging.Target(topic='test', server='server1')
client = messaging.RPCClient(transport, target)
ret = client.call(ctxt={},
                  method='test',
                  arg='myarg1')
client.call({}, 'test', arg='myarg2')
#client.call({}, 'stop')
cctx = client.prepare(namespace='control', version='2.0')
cctx.cast({}, 'stop')
cctx.call({}, 'stop')

运行rpc_server.py

    

   


运行rpc_client.py:

     

     

去掉rpc_cleint.py里面的注释

from oslo_config import cfg
import oslo_messaging as messaging

transport = messaging.get_transport(cfg.CONF)
target = messaging.Target(topic='test', server='server1')
client = messaging.RPCClient(transport, target)
ret = client.call(ctxt={},
                  method='test',
                  arg='myarg1')
client.call({}, 'test', arg='myarg2')
client.call({}, 'stop')
cctx = client.prepare(namespace='control', version='2.0')
cctx.cast({}, 'stop')
cctx.call({}, 'stop')


运行rpc_client.py

    

   


修改rpc_client.py

from oslo_config import cfg
import oslo_messaging as messaging

transport = messaging.get_transport(cfg.CONF)
target = messaging.Target(topic='test', server='server1', namespace='control', version='2.0')
client = messaging.RPCClient(transport, target)

client.call({}, 'stop')

cctx = client.prepare(namespace='control', version='2.0')
cctx.cast({}, 'stop')
cctx.call({}, 'stop')

client.call({}, 'test', arg='myarg2')


运行rpc_client.py

    

    


修改rpc_client.py

from oslo_config import cfg
import oslo_messaging as messaging

transport = messaging.get_transport(cfg.CONF)
target = messaging.Target(topic='test', namespace='control', version='2.0')
client = messaging.RPCClient(transport, target)

client.call({}, 'stop')

cctx = client.prepare(namespace='control', version='2.0')
cctx.cast({}, 'stop')
cctx.call({}, 'stop')


 运行rpc_client.py

    

    

小结:

    (1)rpc_client想要正确调用rpc_server里面endpoint的方法,需要正确设置RPCClient的target的topic、namespace、version等信息。

    (2)RPCClient的target里面的server参数:(字符串类型)客户端可以指定此参数来要求消息的目的地是某个特定的服务器,而不是一组同属某个topic的服务器中的任意一台.

    (3)Target对象的属性在RPCClient对象构造以后,还可以通过prepare()方法修改.可以修改的属性包括exchange,topic,namespace,version,server,fanout,timeout,version_cap和retry.




  • Notification Listener
    Notification Listener和Server类似,一个Notification Listener对象可以暴露多个 endpoint,每个endpoint包含一组方法.但是与Server对象中的endpoint不同的是,这里的endpoint中的方法对应通知消息的不同优先级


  • Notifier
    Notifier用来通过某种transport发送通知消息

Notification_listener和Notifier_send举例

notification_listener.py

from oslo_config import cfg
import oslo_messaging as messaging

def do_something(payload):
    print "recieve:", payload

class NotificationEndPoint(object):
    def warn(self, ctxt, publisher_id, event_type, payload, metadata):
        do_something(payload)

    def error(self, ctxt, publisher_id, event_type, payload, metadata):
        do_something("In NotificationEndPoint")
        do_something(payload)

class ErrorEndpoint(object):
    def error(self, ctxt, publisher_id,event_type, payload, metadata):
        do_something("In ErrorEndpoint")
        do_something(payload)


transport = messaging.get_transport(cfg.CONF)
targets = [
    messaging.Target(topic='notifications'),
    messaging.Target(topic='notifications_bis')
]
endpoints = [
    NotificationEndPoint(),
    ErrorEndpoint(),
]
listener = messaging.get_notification_listener(transport,
                                               targets,
                                               endpoints)

listener.start()
listener.wait()


notifier_send.py

from oslo_config import cfg
import oslo_messaging as messaging

transport = messaging.get_transport(cfg.CONF)
notifier = messaging.Notifier(transport,
                              driver='messaging',
                              topics=['notifications', 'notifications_bis'])

notifier2 = notifier.prepare(publisher_id='compute')
notifier2.error(ctxt={},
                event_type='my_type',
                payload={'content': 'error occurred'})


运行notification_listener.py

   


  

运行notifier_send.py

    
    

    

修改notifier_send.py

from oslo_config import cfg
import oslo_messaging as messaging

transport = messaging.get_transport(cfg.CONF)
notifier = messaging.Notifier(transport,
                              driver='messaging',
                              topics=['notifications'])

notifier2 = notifier.prepare(publisher_id='compute')
notifier2.error(ctxt={},
                event_type='my_type',
                payload={'content': 'error occurred'})

运行notifier_send.py

    

    

   


修改notifier_send.py

from oslo_config import cfg
import oslo_messaging as messaging

transport = messaging.get_transport(cfg.CONF)
notifier = messaging.Notifier(transport,
                              driver='messaging',
                              topics=['notifications'])

notifier2 = notifier.prepare(publisher_id='compute')
notifier2.error(ctxt={},
                event_type='my_type',
                payload={'content': 'error occurred'})
notifier.error(ctxt={},
               event_type='my_type',
               payload={'content2': 'error occurred'})

notifier2.warn(ctxt={},
               event_type='my_type',
               payload={'content': 'warn occurred'})

notifier2.info(ctxt={},
               event_type='my_type',
               payload={'content': 'info occurred'})



运行notifier_send.py

    

    

 

    

  小结:

    (1)发送通知方构造的messaging.Notifier,里面的topics参数指定了一个列表,表示要发生到远程多个的topic。

    (2)通知消息监听方的endpoints,如果都实现了某一级别的方法(比如:error),则都是被调用。

          

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值