美文网首页
Pyro4 分布式计算简单示例

Pyro4 分布式计算简单示例

作者: csdongxian | 来源:发表于2018-08-01 11:37 被阅读0次

    本文的例子来自 Pyro4 官网的 tutorial。这年头,Python的包各种强大,通过Pyro可以轻松进行分布式计算。具体说来,即使被调用方法的对象在远程服务器,Pyro 都可以让我们轻松调用。

    +----------+                         +----------+
    | server A |                         | server B |
    |          |       < network >       |          |
    | Python   |                         |   Python |
    | OBJECT ----------foo.invoke()--------> OBJECT |
    |          |                         |     foo  |
    +----------+                         +----------+
    

    概念

    • 代理(Proxy)
      “代理”是真实对象的替代品。通过操作“代理”,好像被调用方法的对象就在本地。尽管实际操作是在远程服务器上完成的,之后结果会返回给本机调用“代理”的程序。
    • URI
    • Pyro对象(Pyro object)
      是经过Pyro登记的Python对象,经过登记就可以在其他服务器上调用它。类也可以是Pyro对象,之后你就可以通过远程调用告诉Pyro如何创建该类的对象了。本文的示例中,是把类作为Pyro对象。
    • Pyro守护进程(Pyro daemon)
      这是 Pyro 负责监听调用的部分,并将调用分配给正确的对象,并将得到的结果返回给调用者。所有的Pyro对象,都应该登记到一个或者多个守护进程上。
    • Pyro命名服务器(Pyro name server)
      命名服务器为Pyro应用提供地址查询簿。远程对象在Pyro中的名字是逻辑名称,通过命名服务器可以得到精确地地址,从而跟远程对象进行交互。
    • 序列化(Serialization)
      就是将对象转换为比特流的过程,便于网络传输。接收方收到后会进行反序列化(deserialize),得到原来的对象。远程调用方法的参数和返回的数据都要进行序列化。注意,并不是所有对象都可以进行序列化,所有可能存在一些情况,本地可以正常调用,而无法通过 Pyro 进行远程调用。序列化的操作,由Pyro实现,我们无需操作。对Python中序列化有兴趣的,请见此文

    示例

    1. 本地实现

    首先在本地实现代码:有一个Warehouse类,它的实例表示某个具体的仓库,负责保管物品;还有一个Person类,它的实例表示某个人,他可以去仓库存取物品。
    在这个例子中,Janet 和 Henry要去本地的仓库存取物品。既然仓库在本地,当然就很方便了。

    class Warehouse(object):
        def __init__(self):
            self.contents = ["chair", "bike", "flashlight", "laptop", "couch"]
    
        def list_contents(self):
            return self.contents
    
        def take(self, name, item):
            self.contents.remove(item)
            print("{0} took the {1}.".format(name, item))
    
        def store(self, name, item):
            self.contents.append(item)
            print("{0} stored the {1}.".format(name, item))
    
    import sys
    
    class Person(object):
        def __init__(self, name):
            self.name = name
    
        def visit(self, warehouse):
            print("This is {0}.".format(self.name))
            self.deposit(warehouse)
            self.retrieve(warehouse)
            print("Thank you, come again!")
    
        def deposit(self, warehouse):
            print("The warehouse contains:", warehouse.list_contents())
            item = input("Type a thing you want to store (or empty): ").strip()
            if item:
                warehouse.store(self.name, item)
    
        def retrieve(self, warehouse):
            print("The warehouse contains:", warehouse.list_contents())
            item = input("Type something you want to take (or empty): ").strip()
            if item:
                warehouse.take(self.name, item)
    

    最后写一个脚本来运行,如下:

    # This is the code that runs this example.
    from warehouse import Warehouse
    from person import Person
    
    warehouse = Warehouse()
    janet = Person("Janet")
    henry = Person("Henry")
    janet.visit(warehouse)
    henry.visit(warehouse)
    

    运行脚本,得到输出如下:

    $ python visit.py
    This is Janet.
    The warehouse contains: ['chair', 'bike', 'flashlight', 'laptop', 'couch']
    Type a thing you want to store (or empty): television   # typed in
    Janet stored the television.
    The warehouse contains: ['chair', 'bike', 'flashlight', 'laptop', 'couch', >>>  'television']
    Type something you want to take (or empty): couch    # <-- typed in
    Janet took the couch.
    Thank you, come again!
    This is Henry.
    The warehouse contains: ['chair', 'bike', 'flashlight', 'laptop', 'television']
    Type a thing you want to store (or empty): bricks   # <-- typed in
    Henry stored the bricks.
    The warehouse contains: ['chair', 'bike', 'flashlight', 'laptop', 'television', 'bricks']
    Type something you want to take (or empty): bike   # <-- typed in
    Henry took the bike.
    Thank you, come again!
    

    2. 分布式实现

    但是顾客总比商家多,总有些小地方没有被商家覆盖。这该如何是好?
    到分布式这个例子上,Janet和Henry两人在A地,他们要去仓库存取物品,但仓库主体都在B地。有Pyro在,就不用他们大老远跑了。首先仓库要拿到异地办理的资质(成为Pyro对象),然后在A地开一个门面(代理)。Jenet和Henry两人通过门面,就可以存取物品了。门面会把相应物品打包装箱(序列化),然后运到B地,再卸车拆包(反序列化)。仓库运营方(Pyro守护进程)会按要存入物品,再将两人要取的物品找出,装箱打包运到A地,再装卸取件。

    import Pyro4
    
    @Pyro4.expose
    @Pyro4.behavior(instance_mode="single")
    class Warehouse(object):
        def __init__(self):
            self.contents = ["chair", "bike", "flashlight", "laptop", "couch"]
    
        def list_contents(self):
            return self.contents
    
        def take(self, name, item):
            self.contents.remove(item)
            print("{0} took the {1}.".format(name, item))
    
        def store(self, name, item):
            self.contents.append(item)
            print("{0} stored the {1}.".format(name, item))
    
    def main():
        Pyro4.Daemon.serveSimple(
                {
                    Warehouse: "example.warehouse"
                },
                ns = False)
    
    if __name__=="__main__":
        main()
    

    首先在命令行中运行这部分代码,如下:

    $ python warehouse.py
    Object <__main__.Warehouse object at 0x025F4FF0>:
        uri = PYRO:example.warehouse@localhost:51279
    Pyro daemon running.
    

    这部分代码中的 @Pyro4.expose 表示这个类可以进行远程操作,就是仓库要拿到异地办理的执照。因为这里是将一个类注册为Pyro对象,所以要添加@Pyro4.behaviorinstance_mode="single"表示实例被创建后需要负责之后所有的方法调用,参考官方文档
    最后使用main方法,将Warehouse类这个Pyro对象登记到了一个守护进程。仓库有公司进行运营,正式开业啦。运行得到的uri,就是仓库的地址啦,后面需要通过这个地址来找它。
    函数Person类的代码无需修改。最后来看调用的脚本。

    # This is the code that visits the warehouse.
    import sys
    import Pyro4
    from person import Person
    
    if sys.version_info<(3,0):
        input = raw_input
    
    uri = input("Enter the uri of the warehouse: ").strip()
    warehouse = Pyro4.Proxy(uri)
    janet = Person("Janet")
    henry = Person("Henry")
    janet.visit(warehouse)
    henry.visit(warehouse)
    

    通过warehouse = Pyro4.Proxy(uri),我们得到了Warehouse实例的代理。Pyro4自动创建了对应的实例,并负责后面的调用。就是说,B地仓库在A地有门面了,并由该门面承接A地的业务。
    大致做个示意图,见图1。可以看到,在Pyro的帮助下,在计算机A上可以轻松调用计算机B上的对象,只要实现将B上的对象进行一些操作(注册为Pyro对象,登记到守护进程),并把B上对象的uri交给A,并在A上直接把代理当做对象进行调用即可。

    图1. Pyro4 图示。除Pyro外,其他红色字体就是前文提到的一些概念。

    相关文章

      网友评论

          本文标题:Pyro4 分布式计算简单示例

          本文链接:https://www.haomeiwen.com/subject/qbslvftx.html