在openstack中使用两种通信方式,一种是Restful API,另一种是远程过程调用RPC。本片文章主要讲解openstack中RPC的使用方式,以及如何在我们自己的架构中使用RPC。

在我前面的一篇文章《基于Rabbitmq的RPC调用》中已经简单的介绍过RPC,Rabbitmq两种技术,openstack中的RPC调用实现是自己的通用库oslo_message,该库是对基于Rabbitmq实现的RPC的一个封装。

一、技术介绍

nova模块是openstack中最核心的服务,nova模块使用了众多的RPC服务将业务解耦,如:nova-api; nova-conductor; nova-scheduler; nova-compute等。每一个服务都是一个RPC的服务端,同时每一个服务都是一个RPC的客户端。

service服务启动的就是nova的RPC服务

nova各个服务启动时就是开启了一个RPC的服务端,在调用其他服务时会创建一个客户端,通过客户端调用到相应的服务。以nova创建虚拟机为例,在上图的第三步中,nova-scheduler选择好计算节点,将创建虚拟机的信息通过RPC发送给计算节点。代码经过RPC客户端的封装和调用,本文的重点就是如何调用RPC客户端。

 cctxt = self.client.prepare(version=version)

 cctxt.cast(context,'select_destinations',**kw) 

这里的client是 rpc.get_client(target,serializer=serializer),见下图。

通过查找rpc的导入路径,可以发现rpc是从nova模块中导入。

rpc.py 在get_client函数中,返回了messaging的调用。

这里的messaging就是来自oslo_messaging库。

从rpc.py中可知,客户端来自messaging,其实就是oslo_messaging。所以能够看出openstack中RPC的实现封装在oslo_messagin库当中。

oslo_messaging其内部的实现暂时先不管,我们已经知道了调用其接口就能驾驭这个已经封装好的oslo_messaging库来完成自己的一些功能。下面就模拟openstack使用oslo_messaging来完成自己的功能。

二、代码移植

要使用oslo_messagin封装好的RPC,主要步骤分为如下几步:

  1. 安装oslo_messaging库
  2. 安装rabbitmq消息队列
  3. 创建消息队列用户名
  4. 设置用户权限
  5. 创建配置文件
  6. 调用oslo_messaging中客户端,服务器端
  7. 启动服务

1、安装oslo_messaging库

pip install oslo_messaging oslo_config

2、安装rabbitmq

apt-get install rabbitmq-server

3、创建消息队列用户名

rabbitmqctl add_user openstack stack2018

4、设置权限

rabbitmqctl set_permissions openstack ".*" ".*" ".*"

其中步骤2,步骤3,步骤4对很对读者来说肯定十分眼熟,不错,流程和openstack安装Message queue是一样一样的。

5、创建配置文件

my.conf

[DEFAULT]

url = 'rabbit://openstack:stack2018@127.0.0.1:5672/'

用户名:openstack ,密码:stack2018

6、调用oslo_messaging,完成客户端和服务器端

oslo_message_server.py

#coding:utf-8

from oslo_config import cfg
import oslo_messaging
import time
 
class ServerControlEndpoint(object):
 
    def __init__(self, server):
        self.server = server
 
    def stop(self, ctx):
        if self.server:
            self.server.stop()
 
class AddEndpoint(object):
 
    def add(self, ctx, a,b):
        print 'revice message'
        return a+b #从配置文件中加载transport_url。在openstack中,账号、密码、端口号等都是从配置文件中读取,支持可配置的。
#配置文件的内容通过oslo_config库读取。
opts = [
    cfg.StrOpt('url', default='0.0.0.0'),
] CONF = cfg.CONF
CONF.register_opts(opts) CONF(default_config_files=['my.conf']) #transport_url是指定实现RPC的底层技术,可以使rabbitmq,也可以是别的技术
#从my.conf文件中读取到该URL。
transport_url = CONF.url transport = oslo_messaging.get_transport(cfg.CONF,transport_url)  #target用来指定该rpc server监听在哪些队列上。
#target指定了2个参数:topic和server。
target = oslo_messaging.Target(topic='test', server='server1') #可供别人调用的方法类
endpoints = [
    ServerControlEndpoint(None),
    AddEndpoint(),
] #创建Server对象时,需要指定Transport、Target和一组endpoint
server = oslo_messaging.get_rpc_server(transport, target, endpoints,
                                       executor='blocking')
try:
    server.start()
    print 'The Server!'
    while True:
        time.sleep(1)
except KeyboardInterrupt:   
    print("Stopping server")
 
server.stop()

service文件中使用两个openstack通用库,除了oslo_messaging之外,还有一个oslo_config。首先说oslo_config,这个库的主要功能是从配置文件或者命令行中读取特定信息。在openstack的安装过程中,需要配置各种参数,例如nova.conf中配置rabbitmq。

同样,我们在配置文件中也配置了transport_url,通过oslo_config读取配置的值。下面的client也是一样,通过oslo_config读取配置信息。另外一个就是主角oslo_messaging的调用。创建一个RPC的服务端,需要四个参数,分别是:

  1. transport
  2. target
  3. endpoints
  4. executor

他们的功能分别是:

  1. transport        RPC功能的底层实现方法,这里是rabbitmq的消息队列的访问路径
  2. target             指定RPC topic交换机的匹配信息和绑定主机
  3. endpoints      是可供别人远程调用的方法,也是RPC中的远程函数
  4. executor        服务的运行方式,单线程或者多线程

通过这四个参数,形成一个可调用的RPC服务端,服务以阻塞的方式在后台运行。

oslo_message_client.py

#coding:utf-8

from oslo_config import cfg
import oslo_messaging opts = [
    cfg.StrOpt('url', default='helloworld'),
] CONF = cfg.CONF
CONF.register_opts(opts) CONF(default_config_files=['my.conf']) transport_url = CONF.url  
transport = oslo_messaging.get_transport(cfg.CONF,transport_url)  
target = oslo_messaging.Target(topic='test')  
client = oslo_messaging.RPCClient(transport, target)  
r = client.call({}, 'add', a=2,b=3)
print 'result :',r #Target对象的属性在RPCClient对象构造之后,还可以通过prepare()方法修改,
#可以修改的属性包括exchange,topic,namespace,version,server,fanout和retry。
#修改后的target属性只在这个prepare()方法返回的对象中有效。 cctxt = client.prepare(version='1.0')
r_two = cctxt.call({},'add',a=2,b=3)
print 'result_two :',r_two

客户端调用了oslo_messaging.RPCClient()方法,这个方式就是openstack调用oslo_messaging库的方法。通过传入参数:transport:消息处理的端点;target:消息队列中topic的路由关键字,能够准确定位到要发送的消息队列的。另外如果创建的client客户端是共用的,而具体使用时还要修改自己的特性的话,可以使用client.prepare这个方法来修改client的参数。例如代码中使用该方法修改了client的版本号。这样和openstack的代码就是保持了一致。

7、开启服务

先开启服务器

运行客户端,调用远程函数

一次RPC的远程调用就完成了,同时这也是贴近openstack源码的RPC使用方式,很方便在自己的架构中移植这种现有的技术。

最后还有一个小彩蛋。在安装rabbitmq的主机上,进入路径   cd /usr/lib/rabbitmq/bin/,然后执行命令

rabbitmq-plugins enable rabbitmq_management

在浏览器中进入地址 http://localhost:15672,使用账号 guest/guest 登录,能打开rabbitmq的监控界面。

模仿OpenStack写自己的RPC的更多相关文章

  1. tensorflow学习笔记3:写一个mnist rpc服务

    本篇做一个没有实用价值的mnist rpc服务,重点记录我在调试整合tensorflow和opencv时遇到的问题: 准备模型 mnist的基础模型结构就使用tensorflow tutorial给的 ...

  2. 用ES6的class模仿Vue写一个双向绑定

    原文地址:用ES6的class模仿Vue写一个双向绑定 点击在线尝试一下 最终效果如下: 构造器(constructor) 构造一个TinyVue对象,包含基本的el,data,methods cla ...

  3. 手写简易版RPC框架基于Socket

    什么是RPC框架? RPC就是远程调用过程,实现各个服务间的通信,像调用本地服务一样. RPC有什么优点? - 提高服务的拓展性,解耦.- 开发人员可以针对模块开发,互不影响.- 提升系统的可维护性及 ...

  4. 模仿GsonConverter 写的StringConverter 解析String字符串

    使用自己写的StringConverter 来封装的 Converter 来解析String private static final RestAdapter CAMERA_CLIENT_NETWOR ...

  5. 借助bootstrap框架模仿airbnb写的网页

    View HTML .nav a { color: #5a5a5a; font-size: 11px; font-weight: bold; padding: 14px 10px; text-tran ...

  6. js 模仿jquery 写个简单的小demo

    <div id="div" style="background:red;width:100px;height:300px"> 123123123 & ...

  7. 学习写简单的RPC框架demo

    学习实现一个简单的RPC框架. 工程主要目录分级结构: rpc-common: 公共基础包,能力提供包 rpc-provider: 服务提供者 rpc-consumer:服务消费者 rpc-servi ...

  8. 模仿angularjs写了一个简单的HTML模版和js数据填充的示例

    <!DOCTYPE html> <html lang="en" xmlns="http://www.w3.org/1999/xhtml"> ...

  9. Qt自定义圆周动画(360 10.0 的模仿作者写的)

    由于项目需求,需要把一张图片做圆周运动,用到了属性动画,坐标计算等. 在编写代码的过程中,由于太长时间没用sin,cos函数忘了是用弧度为单位,汗呀 下面把代码贴出来 /* * 圆周运动动画 * */ ...

随机推荐

  1. 团队项目(六)- Alpha阶段项目复审(江山代有才人秃)

    排名仅代表个人观点: 小组名字 优点 缺点&Bug报告 排名 中午吃啥队 从测试链接来看,作为一个订餐的APP,有着跟现在的订餐APP相似的功能,很完整,是一个踏踏实实做出来的项目 向购物车中 ...

  2. There is already an object named '#xxxx' in the database.

    这个案例是前几天同事遇到的一个案例,在存储过程中"删除"了一个临时表,然后重新创建这个临时表时遇到"There is already an object named 'x ...

  3. 走进Java Map家族 (1) - HashMap实现原理分析

    在Java世界里,有一个古老而神秘的家族——Map.从底层架构到上层应用,他们活跃于世界的每一个角落.但是,每次出现时,他们都戴着一张冷硬的面具(接口),深深隐藏着自己的内心.所有人都认识他们,却并非 ...

  4. Windows Server 2008远程桌面默认端口更改方法

    win2008远程桌面端口默认是用的是3389端口,但是由于安全考虑,经常我们安装好系统后一般都会考虑把原来的3389端口更改为另外的端口. 本文以改为端口为25608商品为例,讲解一下具体操作过程. ...

  5. SQL MIN() 函数

    MIN() 函数 MIN 函数返回一列中的最小值.NULL 值不包括在计算中. SQL MIN() 语法 SELECT MIN(column_name) FROM table_name 注释:MIN ...

  6. H5播放器内置播放视频(兼容绝大多数安卓和ios)

    关于H5播放器内置播放视频,这个问题一直困扰我很长一段时间,qq以前提供白名单已经关闭,后来提供了同层属性的控制,或多或少也有点差强人意. 后来一次偶然发现一个非常简单的方法可以实现. 只需要给vid ...

  7. 关于 Angular 跨域请求携带 Cookie 的问题

    在前端开发调试接口的时候都会遇到跨域请求的问题.传统的方式是使用 Nginx 反向代理解决跨域.比如所有接口都在 a.com 的域下,通过 Nginx 将所有请求代理到 a.com 的域下即可. 使用 ...

  8. css文字与排版

    目录 文字与排版样式 `font文字样式 排版样式(text) 文字半透明 文字阴影 背景和颜色 基本 背景简写 背景透明 背景缩放 列表样式 表格样式 表格边框样式 折叠边框 设置宽度和高度 表格对 ...

  9. Python selenium —— 一定要会用selenium的等待,三种等待方式解读

    发现太多人不会用等待了,博主今天实在是忍不住要给大家讲讲等待的必要性. 很多人在群里问,这个下拉框定位不到.那个弹出框定位不到…各种定位不到,其实大多数情况下就是两种问题:1 有frame,2 没有加 ...

  10. centos7重置root密码

    修改centos7的root密码重置非常简单,只需要登录系统,执行passwd按enter即可, 但是如果忘记root密码,该如何修改呢 1, 重启系统之后,系统启动进入欢迎界面,加载内核步骤时,选中 ...