zoukankan      html  css  js  c++  java
  • 模仿OpenStack写自己的RPC

    在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的监控界面。

  • 相关阅读:
    VNC跨平台远程桌面的安装与使用
    Apache 的编译安装
    Xming配置
    工作杂记
    自动创建系统用户脚本
    关于linux网络基础记录
    Linux的setup命令启动服务名称和功能
    涉密计算机检查工具
    Nginx压力测试工具之WebBench
    关于系统性能检测的一些使用
  • 原文地址:https://www.cnblogs.com/goldsunshine/p/10205058.html
Copyright © 2011-2022 走看看