myclient.py内容如下
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @File : myclient.py
# @Software: PyCharm
'''
参考文章:
http://blog.csdn.net/happyanger6/article/details/54777429
https://docs.openstack.org/oslo.messaging/ocata/rpcclient.html
关键:
1 RPC Client基础
oslo_messaging.RPCClient(transport, target, timeout=None,, version_cap=None, serializer=None, retry=None)
作用:调用远程RPC服务的类
参数: transport: rpc底层通信,支持rabbit,qpid
target: 消息最终发送的地方
形式:target(exchange,topic,server):
参数:exchange:topic属于的范围,默认为配置文件的control_exchange
topic: 可被远程调用的多个方法
server:消息目的地服务器
2 RPC Call方法
oslo_messaging.RPCClient.call(ctxt, method, **kwargs)
含义:call方法是远程过程调用带有返回值的方法
特点:阻塞直到服务端返回结果
参数: ctxt:上下文字典,可为空
method:被调用的方法名
kwargs:调用该方法传入的参数
返回值:返回被调用远程方法的结果
3 RPC Cast方法
oslo_messaging.RPCClient.cast(ctxt, method, **kwargs)
含义:cast方法是远程过程调用,不带有返回值的方法
参数: ctxt:上下文字典,可为空
method:被调用的方法名
kwargs:调用该方法传入的参数
返回值:无
4 RPC prepare方法
oslo_messaging.RPCClinet.prepare(exchange, topic, namespace, version, server)
作用:就是覆盖RPCClient初始化的一些属性
5 RPC总结:
实际就是一个远程调用,客户端通过rpc调用服务端的方法。
通过指定方法名和对应参数来进行调用;
RPCClient端调用过程:
1) 通过配置文件获取transport,指定topic初始化target,
2) 用transport和target初始化RPCClient
3) 最后调用RPCClientr的call方法或者cast方法
RPCServer端调用过程:
1) 根据配置初始化transport,根据topic,server等初始化target
2) 指定endpoints数组,每个元素是一个类实例
3) 用transport,target,endpoints,executor来构造rpc server
4) 执行rpc server的start()方法
注意: 客户端和服务端通过target进行连接,都需要指明topic参数。
'''
from oslo_config import cfg
import oslo_messaging as messaging
def rpcCall():
# 消息中间件,rabbitMQ或者Qpid等
transport = messaging.get_transport(cfg.CONF)
target = messaging.Target(topic='test')
client = messaging.RPCClient(transport, target)
ret = client.call(ctxt={},
method='processCall',
name='hello rpc call')
print "######## End call, result: %s" % ret
def rpcCast():
transport = messaging.get_transport(cfg.CONF)
target = messaging.Target(topic='test')
client = messaging.RPCClient(transport, target)
cctx = client.prepare(namespace='control', version='2.0')
cctx.cast({}, 'processCast', name='hello rpc cast')
print "######## End cast"
def process():
rpcCall()
rpcCast()
if __name__ == "__main__":
process()
myserver.py内容如下
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @File : myserver.py
# @Software: PyCharm
from oslo_config import cfg
import oslo_messaging as messaging
'''
参考:
https://docs.openstack.org/ironic/latest/_modules/oslo_messaging/rpc/server.html
关键:
1 总结初始化RPC Server步骤:
1) 根据配置初始化transport,根据topic,server等初始化Target
2) 指定endpoints数组,每个元素是一个类实例
3) 用transport,target,endpoints,executor来构造rpc server
4) 执行rpc server的start()方法
2 get_rpc_server方法分析
oslo_messaging.get_rpc_server(transport, target, endpoints, executor='blocking')
作用:构建一个RPC服务器
参数:
transport: rpc通信,支持rabbit,qpid;可通过oslo.messaging.get_transport来获得transport对象实例的句柄
从cfg对象中读取transport_url,rpc_backend,control_exchange信息来构造Transport对象,
其中rpc_backend默认值: rabbit; control_exchange默认值:openstack
target: 封装消息目的地所有信息,包含exchange, topic, server, namespace, version等信息
endpoints: 端口数组,每个元素是类对象
executor:消息执行器,可选:eventlet和threading。决定消息如何收到和分发
eventlet:
threading:协程处理消息接收,不阻塞
blocking:阻塞,直到调用stop()退出
serializer:可选的实体序列化器
3 RPCServer和RPCClient中关于target部分注意点
注意:每个endpoint可能会有一个target属性,有namespace和version字段
默认是 null namespace和1.0版本,用来兼容不同的topic创建的Target构造的RPCClient
调用,样例如下。
class RpcCastEndpoint(object):
target = messaging.Target(namespace='control',version='2.0')
因为有的RPC Client是用下面方式创建:
client = messaging.RPCClient(transport, target)
cctx = client.prepare(namespace='control', version='2.0')
所以两边要匹配
'''
class RpcCastEndpoint(object):
'''
注意:每个endpoint可能会有一个target属性,有namespace和version字段
默认是 null namespace和1.0版本,用来兼容不同的topic创建的Target构造的RPCClient
调用
'''
target = messaging.Target(namespace='control',version='2.0')
def __init__(self):
pass
def processCast(self, ctx, name):
# print "####### RpcCastEndpoint.processCast##########"
print name
class RpcCallEndpoint(object):
def __init__(self):
pass
def processCall(self, ctx, name):
# print "####### RpcCallEndpoint.processCall"
print name
return name
def startRpcServer():
transport = messaging.get_transport(cfg.CONF)
target = messaging.Target(topic='test',
server='server1')
endpoints = [
RpcCastEndpoint(),
RpcCallEndpoint(),
]
server = messaging.get_rpc_server(transport, target, endpoints,
executor='blocking')
server.start()
server.wait()
def process():
startRpcServer()
if __name__ == "__main__":
process()
先执行:
python myserver.py
然后执行
python myclient.py
即可显示最终结果