Openstack_通用技术_RPC 远程异步调用

摘要:
目录目录RPC通过HTTPRequest调用操作函数的RPC实现示例环境接收HTTPRequestRPC调用。特定操作函数测试RPCRPC:同一项目中不同服务进程之间的交互模式。问题1:Openstack项目APIService/ManageService中有多个不同的流程服务通过HTTPRequest调用操作函数的RPC实现示例包括以下两个过程实现:用于接收HTTPRequestRPC调用操作函数环境Devstack的L版本。该示例在定制的Openstack项目中实现。有关详细信息,请参阅自动生成新Openstack项目的开发框架。
目录

RPC

RPC: 同一个项目内的不同服务进程之间的交互方式。为不同的进程服务提供了 call()(同步) 和 cast()(异步) 两种调用方式。

问题 1: 在一个 Openstack 项目中拥有多个不同的进程服务,EG. API Service/Manage Service。 当我们通过 Client 发送 API Request 去调用 Manage Service 执行一个操作任务时,我们会希望这个调用的结果是能够快速响应到 Client 的(保证用户体验)。

问题 2: 而且进程服务之间的调用我们还需要考虑如何有效的避免进程服务之间调用的阻塞问题。EG. API Service 调用 Manage Service 时,如果不能及时的将 API Service 释放掉,那么 API Request 就会因为被占用,而无法处理新的请求。

对于上面两个问题,我们可以通过将具体的执行过程响应过程分离来达到理想的效果。这也是 RPC 和 API 存在的原因之一。

一个通过 HTTP Request 调用操作函数的 RPC 实现样例

包含了下列两个过程实现:

  • 接收 HTTP Request
  • RPC 调用操作函数

环境

Devstack 用的 L 版,样例在自定义的 Openstack 项目中实现,详见自动化生成 Openstack 新项目开发框架

接收 HTTP Request

# project/api/v1/router.py

from project.api.v1 import new_resource

class APIRouter(octopunch.api.openstack.APIRouter):
    """Routes requests on the API to the appropriate controller and method."""
    ExtensionManager = extensions.ExtensionManager

    def _setup_routes(self, mapper, ext_mgr):
        self.resources['versions'] = versions.create_resource()
        mapper.connect("versions", "/",
                       controller=self.resources['versions'],
                       action='show')

        mapper.redirect("", "/")

        self.resources['new_resource'] = new_resource.create_resource(ext_mgr)
        mapper.resource('new_resource', 'new_resource',
                        controller=self.resources['new_resource'])
  • 将 Resource 和 HTTP 方法绑定到 Controller 的 Action 函数中
# project/api/v1/new_resource.py

class NewResourceController(wsgi.Controller):

    def __init__(self, ext_mgr):
        self.ext_mgr = ext_mgr
        super(NewResourceController, self).__init__()

    # Create() 对应了 HTTP 的 POST 方法
    @wsgi.serializers()
    def create(self, req, body):
        """Create a NewResource."""
        context = req.environ['project.context']

        # Sync the project database.
        self.new_resource_api.db_sync(context)

def create_resource(ext_mgr):
    """project resource factory method."""
    return wsgi.Resource(NewResourceController(ext_mgr))

上述两个文件实现了通过 HTTP Request 的 POST 方法来执行指定的 Create() 函数。

RPC 调用具体的操作函数

  • 通过 API 调用 RPC-API
# project/new_resource/api.py

# import rpcapi module
from project.new_resource import rpcapi as new_resource_rpcapi

class API(base.Base):
    """API for interacting with the new_resource manager."""

    def __init__(self, db_driver=None, image_service=None):
        self.new_resource_rpcapi = new_resource_rpcapi.NewResourceAPI()
        super(API, self).__init__(db_driver)

    # 定义调用 rpcapi 的接口函数
    def db_sync(self, context):
        """Call rpc api to start db sync for new_resource database."""
        self.new_resource_rpcapi.db_sync(context)

API 的存在是为了能够快速的响应请求,至于之后的执行过程交由 RPC-API 和 Manager 来处理

  • rpc-api.py 调用 manager.py
    rpcapi.py 定义的 RPC 接口函数会自动的映射到 manager.py 中指定的处理函数。
# project/new_resource/rpcapi.py

class NewResourceAPI(object):

    def __init__(self):
        super(NewResourceAPI, self).__init__()
        target = messaging.Target(topic=CONF.manage_topic,
                                  version=self.RPC_API_VERSION)
        serializer = objects_base.ProjectObjectSerializer()
        self.client = rpc.get_client(target, version_cap='1.8',
                                     serializer=serializer)

    # 定义 rpcapi 函数,使用 cast 异步调用方式
    def db_sync(self, context):
        cctxt = self.client.prepare()
        # 指定 rpcapi 的调用方式,和指定映射到 manager.py 的处理函数
        cctxt.cast(context, 'db_sync')

RPC-API 的存在是为了快速的响应进程服务之间的调用请求。

# project/new_resource/manager.py
class NewResourceManager(manager.Manager):

    RPC_API_VERSION = '1.8'

    target = messaging.Target(version=RPC_API_VERSION)

    def __init__(self, service_name=None, *args, **kwargs):
        super(NewResourceManager, self).__init__(*args, **kwargs)
        self._startup_delay = True

    def init_host_with_rpc(self):
        eventlet.sleep(CONF.periodic_interval)
        self._startup_delay = False

    def db_sync(self, context):
        print "这里是具体的 RPC 操作函数"

小结
Openstack 的 PRC 调用的过程为: api.pyrpcapi.pymanager.py
详见:Openstack Nova 源码分析 — RPC 远程调用过程

测试
  • 启动 API 服务
project-api --config-file /etc/project/proname.conf
  • 启动 Manager 服务
project-manager --config-file /etc/project/project.conf
  • 发送 HTTP 请求
curl -i 'http://<Service_host_ip>:<service_port>/v1/<project_id>/<ResourceUrl>' -X POST -H "Content-Type: application/json" -H "X-Auth-Project-Id: admin" -H "X-Auth-Token: <token_id>" -d '<body_content_dict>'

注意: 样例需要根据自身开发环境进行调整,

免责声明:文章转载自《Openstack_通用技术_RPC 远程异步调用》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇爬取csdn的数据与解析存储(9)centos 网卡名称修改下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

将html导入到excel或word itprobie

1>通过js实现,在页面的前台调用微软office的com组件,要求用户必须安装office,启动automation服务,并且在浏览器中启用未注册的activex选项. function importToExcel(tableid) { var curTbl = document.getElementById(tableid); t...

openstack多节点部署运维

一、packstack单点部署 1、配置虚拟机NAT网络连接 查看vmware的NAT网络默认配置 vmwarestation软件点击 上方“编辑”,选择“虚拟网络编辑器”找到vmnet10,是NAT模式,子网地址是172.25.2.0,子网掩码是:255.255.255.0.再点击“NAT设置”,可看到它的网关:172.25.2.2 配置当前虚拟机的网络...

nginx配置一、二级域名、多域名对应(api接口、前端网站、后台管理网站)

前提:安装好nginx,如果已经启动nginx,先停止,命令: ./usr/local/nginx/sbin/nginx -s stop 修改nginx配置 vi /usr/local/nginx/conf/nginx.conf 配置好以后的nginx.conf文件内容: #user nobody; worker_processes 1;...

SharedPreferences 详解(多进程,存取数组解决方案)

一、SharedPreferences基本概念 文件保存路径:/data/data/<包名>/shared_prefs目录下目录下生成了一个SP.xml文件 SharedPreferences对象本身只能获取数据而不支持存储和修改,存储修改是通过Editor对象实现。 实现SharedPreferences存储的步骤如下: 根据Context...

LTE信令流程之专用承载流程介绍

https://www.mscbsc.com/viewnews-102220.html  感谢作者! 【LTE基础知识】LTE信令流程之专用承载流程介绍 发布: 2014-08-11 16:40 | 作者: MSCBSC | 来源: 移动通信网 | 字体:  小  中  大  相关专题:基础知识无线   专用承载建立流程    专用承载建立流程说...

Android自定义组合控件

今天和大家分享下组合控件的使用。很多时候android自定义控件并不能满足需求,如何做呢?很多方法,可以自己绘制一个,可以通过继承基础控件来重写某些环节,当然也可以将控件组合成一个新控件,这也是最方便的一个方法。今天就来介绍下如何使用组合控件,将通过两个实例来介绍。第一个实现一个带图片和文字的按钮,如图所示: 整个过程可以分四步走。第一步,定义一个lay...