• firefly的rpc。。


    firefly使用了twisted的pb 来实现rpc:

    http://twistedmatrix.com/documents/current/core/howto/pb-usage.html

    服务端
    #!/usr/bin/env python
    
    # Copyright (c) Twisted Matrix Laboratories.
    # See LICENSE for details.
    
    from twisted.spread import pb
    from twisted.internet import reactor
    
    class One(pb.Root):
        def remote_takeTwo(self, two):
            print "received a Two called", two
            print "telling it to print(12)"
            two.callRemote("print", 12)
    
    reactor.listenTCP(8800, pb.PBServerFactory(One()))
    reactor.run()
    
    客户端
    
    #!/usr/bin/env python
    
    # Copyright (c) Twisted Matrix Laboratories.
    # See LICENSE for details.
    
    from twisted.spread import pb
    from twisted.internet import reactor
    
    class Two(pb.Referenceable):
        def remote_print(self, arg):
            print "Two.print() called with", arg
    
    def main():
        two = Two()
        factory = pb.PBClientFactory()
        reactor.connectTCP("localhost", 8800, factory)
        def1 = factory.getRootObject()
        def1.addCallback(got_obj, two) # hands our 'two' to the callback
        reactor.run()
    
    def got_obj(obj, two):
        print "got One:", obj
        print "giving it our two"
        obj.callRemote("takeTwo", two)
    
    main()
    

      

    1.客户端通过factory.getRootObject() 获取def,并增加回调函数。其第一个参数为pb.Root(未证实),然后借助callRemote方法条用服务端的东西

    2.可以在客户端首次连接的时候,将客户端的Referenceable传给服务端。。服务端进行保存。。之后需要像客户端发送消息的时候。。只要使用客户端的callRemote就OK了

    root.py 实现PB的server功能

    node.py 实现PB的client功能。

    child.py 每个client连接上root都会初始化一个child来保存该client的相关信息,并且将这些child通过manager来管理。

    manager.py 管理root的child,通过一个字典self._childs = {},实现一个增删改的小管理器。

    reference.py 如果你看了前面twisted官网的介绍就会知道,node只要实例化一个 pb.Referenceable 类,并把它传递给root,那么root就能够把这个pb.Referenceble当成句柄来远程调用client的函数。

    下面我们看看firefly的实现。

    1.实例化客户端node,实例了客户端工厂,_reference和name

    2.客户端建立连接:node.connect ,并条用了服务端的takeProxy。建立了通道

    def callRemote(obj,funcName,*args,**kw):
        '''远程调用
        @param funcName: str 远程方法
        '''
        return obj.callRemote(funcName, *args,**kw)
    
    
    。。。。。。
    。。。。。。
        def takeProxy(self):
            '''像远程服务端发送代理通道对象
            '''
            deferedRemote = self._factory.getRootObject()
            deferedRemote.addCallback(callRemote,'takeProxy',self._name,self._reference)
    

    2.服务端的takeProxy。根据第一次传过来的客户端名称和reference实例化了child,并保存到childManage中

    3.执行了首次连接处理。doChildConnect。。请看rootapp.py.如果不看这里你一定会很奇怪,gate的root怎么和其他的server连接起来的。

    def _doChildConnect(name,transport):
        """当server节点连接到master的处理
        """
        server_config = GlobalObject().json_config.get('servers',{}).get(name,{})
        remoteport = server_config.get('remoteport',[])
        child_host = transport.broker.transport.client[0]
        root_list = [rootport.get('rootname') for rootport in remoteport]
        GlobalObject().remote_map[name] = {"host":child_host,"root_list":root_list}
        #通知有需要连的node节点连接到此root节点
        for servername,remote_list in GlobalObject().remote_map.items():
            remote_host = remote_list.get("host","")
            remote_name_host = remote_list.get("root_list","")
            if name in remote_name_host:
                GlobalObject().root.callChild(servername,"remote_connect",name,remote_host)
        #查看当前是否有可供连接的root节点
        master_node_list = GlobalObject().remote_map.keys()
        for root_name in root_list:
            if root_name in master_node_list:
                root_host = GlobalObject().remote_map[root_name]['host']
                GlobalObject().root.callChild(name,"remote_connect",root_name,root_host)
    

    4.服务端调用客户端。root.callChildByName.会在childManager中找到child并使用其中的reference,最终条用代码为:ProxyReference(pb.Referenceable):中的

        def remote_callChild(self, command,*arg,**kw):
            '''代理发送数据
            '''
            return self._service.callTarget(command,*arg,**kw)
    

    5.客户端条用,服务端使用,node.callRemote..其中最终使用的方法为:root.py中的。

     def remote_callTarget(self,command,*args,**kw):
            '''远程调用方法
            @param commandId: int 指令号
            @param data: str 调用参数
            '''
            data = self.service.callTarget(command,*args,**kw)
            return data

    6.从上可以看到。。使用service的意义何在了。。。

  • 相关阅读:
    聊聊“装箱”在CLR内部的实现
    Jenkins多环境持续集成架构实践
    .NET Core 学习资料精选:进阶
    .NET Core 学习资料精选:入门
    Docker 常用命令(.NET Core示例)
    Vistual Studio 安装、Sql Server 安装
    .NET项目迁移到.NET Core操作指南
    站点部署,IIS配置优化指南
    .NET Core开源:IIS集中化Web管理工具
    jenkins:一键回滚站点集群
  • 原文地址:https://www.cnblogs.com/zhepama/p/3536408.html
Copyright © 2020-2023  润新知