简单学习rpc -- thrift 远程调用流程简单分析

Blog地址:https://www.jiangdog.com/blog/rpc-thrift-source-code

了解RPC的流程

通过阅读你应该知道的 RPC 原理可以很清楚的了解到一次RPC调用的流程。
1. 客户端client调用本地代码的方式调用服务代码(实际上应该是调用的服务代码在client的存根中的代码)。
2. client stub接收到后将所调用的服务名,参数等编码成适合网络传输的消息体。
3. client stub找到请求的服务地址,并将消息体发送给服务器。
4. server stub接收到消息后对消息体进行反序列化。
5. server stub通过解码后得到的服务名,参数等找到服务器本地的服务代码。
6. 调用server服务端本地代码得到结果。
7. server stub将得到的结果编码成消息体返回给client stub。
8. client stub接收到结果消息体后再解码。
9. client 得到最终结果。

可以发现如果是一个RPC框架需要:

  • 服务端server stub存根, 客户端 client stub存根(实际上是服务接口的存根实现)。
  • 解码,编码。包括了消息体的数据结构和序列化。
  • 通信。

简单分析thrift如何实现rpc

回顾一下一个简单thrift demo的实现流程。
1. 利用IDL编写.thrift文件,其中应该定义了各个服务的接口(服务名,参数,返回值等)。
2. 利用thrift compiler对.thrift文件进行编译,生成对应语言的服务接口文件(包括了客户端部分和服务端)。
3. 服务端: 实现服务接口 -> 指定监听服务地址和端口,协议类,传输层 -> 开启监听
4. 客户端: 制定请求服务地址和端口,协议类,传输层 -> 实例化服务接口的客户端client对象,调用本地存根实现的方法。

客户端通过接口文件中的客户端部分生成一个Client对象,这个客户端对象中包含所有接口函数的存根实现,然后用户代码就可以通过这个Client对象来调用thrift文件中的那些接口函数了

5.服务接口函数的存根将调用请求发送给服务器,thrift服务端利用接受到的调用的函数名和参数等,找到服务接口的具体实现,并返回给client对象。
6. client对象再将返回值返回给用户。

thrift各部分代码

thrift实现rpc主要依靠的是以下几个部分:
1. TTransport:传输类
2. TProtocol: 协议类
3. Processer:客户端执行类
4. Client:客户端存根类
5. TSocket和TServerSocket:封装了socket部分方法(实际也是传输类)。

直接看各部分的代码比较晦涩难懂,根据pingpong demo代码,简单分析整个流程:

pp_client.py:

def ping_client():
    try:
        # common
        tsocket = TSocket.TSocket('127.0.0.1', 8080)  # 通信socket并设置请求ip和端口
        transport = TTransport.TBufferedTransport(tsocket)  # 传输类型

        # single service
        protocol = TBinaryProtocol.TBinaryProtocol(transport)  # 通信协议二进制协议(与服务器端保持一致)
        pingpong_client = PingPong.Client(protocol)

        transport.open()  # 打开socket传输并建立连接

        print("The return value is : ")
        print(pingpong_client.ping())
        print("............")
        transport.close()
    except Thrift.TException as tx:
        print('%s' % tx.message)

如上述代码所示:
1. pingpong_client = PingPong.Client(protocol)实例化生成的pingpong_client实际是包含了所有服务接口函数的存根实现,是由thrift compiler编译.thrift文件生成的。

class Iface(object):
    def ping(self):
        pass

class Client(Iface):
    def __init__(self, iprot, oprot=None):
        self._iprot = self._oprot = iprot
        if oprot is not None:
            self._oprot = oprot
        self._seqid = 0

    def ping(self):
        self.send_ping()
        return self.recv_ping()

    def send_ping(self):
        ...

    def recv_ping(self):
        ...
        TApplicationException(TApplicationException.MISSING_RESULT

你可能感兴趣的:(python,thrift,python)