一个简单RPC框架是怎样炼成的(II)——制定RPC消息

开局篇我们说了,RPC框架的四个核心内容

  1. RPC数据的传输
  2. RPC消息 协议
  3. RPC服务注冊
  4. RPC消息处理

以下,我们先看一个普通的过程调用

class Client(object):

    def __init__(self):
        self.remote = None

    ##
    # 内部是托付给远程remote对象来获取结果。
    def sayHello(self):
        if self.remote: return self.remote.sayHello()
        else : return None

class Server(object):

    def __init__(self):
        pass

    def sayHello(self):
        return 'Hello World'    

if __name__ == '__main__':
    server = Server()
    client = Client()
    client.remote = server
    print(client.sayHello())

这是一个常见的过程调用的样例,client调用sayHello,实际托付给Server的sayHello方法来实现。但他不是RPC调用。由于起码不是远程的。另外,也没有我们提到的四个核心内容。

于是我们的任务就是通过一点点的代码改动,为其引入RPC框架。

第一步,订协议。

俗话说得好,没有规矩不成方圆。

还是继续能多简单就多简单。

RPC请求:Request, 包括一个请求id 和 一个请求命令,如‘sayHello‘

class Request(object):
    '''
    @RPC请求,包括命令id和请求内容两部分。

这个实现,与详细的RPC协议相关。
    @这里是简化起见,採用python自身的字典作为其协议的数据结构
    '''

    def __init__(self):
        '''
        Constructor
        '''
        self.id = 0 #id的作用在于将Request和Response建立绑定关系.在异步调用时就实用
        self.command = None #sayHello

    def __str__(self):
        return ''.join(('id: ', str(self.id),  '   command: ', str(self.command)))

相同的,对RPC Response,也定义例如以下

class Response(object):
    '''
    @RPC回复。 包括答复id和运行结果两部分内容。当中答复id与相应的请求id一致。

@简单起见。协议的实现使用python自家的字典
    '''

    def __init__(self):
        '''
        Constructor
        '''
        self.id = 0
        self.result = None

    def __str__(self):
        return ''.join(('id: ', str(self.id),  '   result: ', str(self.result)))

定义好协议之后,我就对Client稍作改动,将原来直接的接口调用 self.remote.sayHello更改为 send Request (command=‘sayHello‘)

    def sayHello(self):
        req = Request() // 构建一个RPC请求消息
        req.id = 1
        req.command = 'sayHello'
        return self.request(req)

    def request(self, req):
        rsp = self.remote.procRequest(req) // 将请求消息发送给远程服务端。

但由于传输层这里还没实现,所以先临时还是直接调用远端接口
        return rsp.result

然后。服务端也要对应改动,须要依据request请求中的command命令,调用详细的方法。并将运行结果封装到Response中,返回给client。

def procRequest(self,req):
        rsp = Response()
        rsp.id = req.id
        if req.command == 'sayHello':
            rsp.result = self.sayHello()
        else:
            raise Exception("unknown command")

        return rsp

到这里。RPC框架中的RPC消息已经初具雏形,只是

  • 我们并没有实现对应的encode和decode方法,没有基于能够跨设备的字符串传输,而是直接的内存变量传递。
  • 如今的RPC request不支持带參数的请求命令。如add(a, b), 怎样在RPC消息中描写叙述參数a,b 。

这些问题我们在后面还会继续展开处理

时间: 2024-10-12 02:19:20

一个简单RPC框架是怎样炼成的(II)——制定RPC消息的相关文章

一个简单RPC框架是如何炼成的(II)——制定RPC消息

开局篇我们说了,RPC框架的四个核心内容 RPC数据的传输. RPC消息 协议 RPC服务注册 RPC消息处理 下面,我们先看一个普通的过程调用 class Client(object): def __init__(self): self.remote = None ## # 内部是委托给远程remote对象来获取结果. def sayHello(self): if self.remote: return self.remote.sayHello() else : return None cla

一个简单RPC框架是如何炼成的(IV)——实现RPC消息的编解码

之前我们制定了一个很简单的RPC消息 的格式,但是还遗留了两个问题,上一篇解决掉了一个,还留下一个 我们并没有实现相应的encode和decode方法,没有基于可以跨设备的字符串传输,而是直接的内存变量传递. 现在的RPC request不支持带参数的请求命令.如add(a, b), 如何在RPC消息中描述参数a,b . 下面我们处理掉这个编解码问题. 实际的RPC应用基本都是跨机器连接,所以无法直接传递内存变量,也就是说还需要将消息编码成 诸如字符串一类的可以跨设备传输的内容.具体的RPC消息

一个简单RPC框架是如何炼成的(V)——引入传输层

开局篇我们说了,RPC框架的四个核心内容 RPC数据的传输. RPC消息 协议 RPC服务注册 RPC消息处理    接下来处理数据传输.实际应用场景一般都是基于socket.socket代码比较多,使用起来也比较麻烦.而且具体的传输通道使用socket或者其他的方式,如更上层的http,或者android里的binder,都是可替换的,只是具体的一种实现而已.所以,这里我就偷个懒,只是引入一个很简单的Connection类,用来描述一下如何将数据传输 这一层给独立出来. 首先简单列出Conne

一个简单RPC框架是如何炼成的(VI)——引入服务注册机制

开局篇我们说了,RPC框架的四个核心内容 RPC数据的传输. RPC消息 协议 RPC服务注册 RPC消息处理 接下来处理RPC服务的注册机制.所谓注册机制,就是Server需要声明支持哪些rpc方法,然后当客户端发送调用某个声明的rpc方法之后,服务端能自动找到执行该请求的具体方法.以实际的例子为例,这是现在server端处理RPC请求的代码 def procRequest(self): # 循环读取并处理收到的客户端请求 while True: req = self.conn.recv()

一个简单RPC框架是如何炼成的(I)——开局篇

开场白,这是一个关于RPC的相关概念的普及篇系列,主要是通过一步步的调整,提炼出一个相对完整的RPC框架. RPC(Remote Procedure Call Protocol)--远程过程调用协议,基于C/S模型.网络上有一篇文章写得不错,可以去了解一下相关概念深入浅出RPC 这里,直接使用一下上面作者的一个示意图 总结下来就是有4块核心内容 RPC数据的传输.如上面的RPCConnector,RPCChannel.它们主要负责数据传输这一块, 具体客户端与服务器之间的连接是不是socket连

一个简单RPC框架是怎样炼成的(VI)——引入服务注冊机制

开局篇我们说了.RPC框架的四个核心内容 RPC数据的传输. RPC消息 协议 RPC服务注冊 RPC消息处理 接下来处理RPC服务的注冊机制.所谓注冊机制,就是Server须要声明支持哪些rpc方法.然后当client发送调用某个声明的rpc方法之后,服务端能自己主动找到运行该请求的详细方法.以实际的样例为例.这是如今server端处理RPC请求的代码 def procRequest(self): # 循环读取并处理收到的client请求 while True: req = self.conn

一个简单RPC框架是如何炼成的(III)——实现带参数的RPC调用

上一篇,我们制定了一个很简单的RPC消息 的格式,但是还遗留了两个问题 我们并没有实现相应的encode和decode方法,没有基于可以跨设备的字符串传输,而是直接的内存变量传递. 现在的RPC request不支持带参数的请求命令.如add(a, b), 如何在RPC消息中描述参数a,b . 我先来实现第二个问题,即带参数的RPC调用. 其实,也没什么太大不同.既然是要带参数,那只能扩展原来的Request消息了,加个parameter成员,用于表示参数,具体的格式采用字典方式,{ 'arg1

Ogre: 建立一个简单的框架——关于场景节点

[转载请保证内容的完整性和正确性] 建立一个简单的框架——关于场景节点 如果我们要做一个类似于<跑跑卡丁车>的游戏,人物模型是需要随着卡丁车模型一起进行各种变换的(平移.旋转等),我们需要分别计算两个关联的模型的位置吗?这样能解决问题,但是太麻烦了,利用Ogre的场景节点可以很方便地解决这种问题. 添加一个新的模型 之前添加的模型都是由3DMAX等软件导出的模型,接下来我们利用Ogre生成一个Cube模型. 1 //DemoManager.cpp 2 Ogre::ManualObject* c

Ogre: 建立一个简单的框架——响应键盘事件

[转载请保证内容的完整性和正确性] 建立一个简单的框架——响应键盘事件 上一节我们在场景中添加了一个机器人,这一节我们将建立一个FrameListener类(顾名思义,这是一个侦听类),来控制模型进行移动. 创建FrameListener类 FrameListener类主要负责事件的侦听,如帧结束.键盘输入等事件.它继承自ExampleFrameListener类,如果需要的话还可以继承KeyListener(键盘事件).MouseListener(鼠标事件)和JoyStickListener(