• Thrift中实现Java与Python的RPC互相调用


    场景

    Thrift介绍以及Java中使用Thrift实现RPC示例:

    https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/108689413

    在上面讲了在Java中使用Thrift实现远程过程调用。实现了在客户端调用服务端的方法。

    但是这都是在Java项目中。

    Thrift的强大之处并不止于此,如果想实现在两个不同的语言的服务端可客户端中实现RPC,

    比如在Java客户端中调用Python服务端的方法或者在Python客户端中调用Java服务端的方法。

    注:

    博客:
    https://blog.csdn.net/badao_liumang_qizhi
    关注公众号
    霸道的程序猿
    获取编程相关电子书、教程推送与免费下载。

    实现

    前面在使用Thrift生成Java代码时的thrift文件为

    namespace java thrift.generated
    
    typedef i16 short
    typedef i32 int
    typedef i64 long
    typedef bool boolean
    typedef string String
    
    struct Person {
        1:optional String username,
        2:optional int age,
        3:optional boolean married
    }
    
    exception DataException {
        1:optional String message,
        2:optional String callback,
        3:optional String date
    }
    
    service PersonService {
        Person getPersonByUsername(1:required String username) throws (1:DataException dataException),
        void savePerson(1:required Person person) throws(1:DataException dataException)
    }

    为了能生成代码,添加一个py的namespace

    namespace py py.thrift.generated

    添加之后的完成代码

    namespace java thrift.generated
    namespace py py.thrift.generated
    
    typedef i16 short
    typedef i32 int
    typedef i64 long
    typedef bool boolean
    typedef string String
    
    struct Person {
        1:optional String username,
        2:optional int age,
        3:optional boolean married
    }
    
    exception DataException {
        1:optional String message,
        2:optional String callback,
        3:optional String date
    }
    
    service PersonService {
        Person getPersonByUsername(1:required String username) throws (1:DataException dataException),
        void savePerson(1:required Person person) throws(1:DataException dataException)
    }

    之前已经将thrift的编译器添加进环境变量,所以在IDEA中的Ternimal中使用其生成Python代码

    thrift --gen py src/thrift/MyData.thrift

    后面跟的是thrift文件的位置

    此时会在项目根目录下生成gen-py目录,里面就是生成的python代码

    新建Python项目PyThrift,这里使用PyCharm再打开Ternimal,使用pip安装thrift

    pip install thrift

    然后将上面生成的python代码的gen-py下面的py目录和__init_.py复制到Pycharm中的Python项目中

    Python客户端请求Java服务端

    在Python项目中新建py_client.py

    # -*- coding:utf-8 -*-
    __author__='公众号:霸道的程序猿'
    
    from py.thrift.generated import PersonService
    from py.thrift.generated import ttypes
    from thrift import Thrift
    from thrift.transport import TSocket
    from thrift. transport import TTransport
    from thrift. protocol import TCompactProtocol
    
    try:
        tSocket = TSocket.TSocket('localhost',8899)
        tSocket.setTimeout(600)
        transport = TTransport.TFramedTransport(tSocket)
        protocol = TCompactProtocol.TCompactProtocol(transport)
        client = PersonService.Client(protocol)
    
        transport.open()
    
        person = client.getPersonByUsername("公众号:霸道的程序猿")
    
        print (person.username)
        print (person.age)
        print(person.married)
    
        print('--------------------')
    
        newPerson = ttypes.Person()
        newPerson.username('公众号:霸道的程序猿')
        newPerson.age = 50
        newPerson.married = True
    
        client.savePerson(newPerson)
    
        transport.close()
    
    except Thrift.TException as tx:
        print(tx.message)

    注意这里的Python客户端所使用的通信层和传输层的协议要和上面博客中Java客户端使用的一致。

    然后运行Java中的服务端,以及Python中的客户端

    可以看到Python的客户端调用了Java服务端的两个方法成功。

    Java客户端调用Python服务端

    在Python项目中新建PersonServiceImpl.py作用与之前Java服务端的实现类相同都是实现

    thrift中struct中定义的接口方法。

    # -*- coding:utf-8 -*-
    __author__='公众号:霸道的程序猿'
    
    from py.thrift.generated import ttypes
    
    class PersonServiceImpl:
        def getPersonByUsername(self,username):
            print('Python 服务端获取到客户端传来的参数:'+username)
    
            person = ttypes.Person()
            person.username = username
            person.age = 50
            person.married = True
            return  person
        def savePerson(self,person):
            print('Python 服务端获取客户端的参数:')
    
            print(person.username)
            print(person.age)
            print(person.married)

    然后再新建服务端py_server.py

    # -*- coding:utf-8 -*-
    __author__='公众号:霸道的程序猿'
    
    from py.thrift.generated import PersonService
    from PersonServiceImpl import PersonServiceImpl
    from thrift import Thrift
    from thrift.transport import TSocket
    from thrift.transport import TTransport
    from thrift.protocol import  TCompactProtocol
    from thrift.server import TServer
    
    try:
        personServiceHandler = PersonServiceImpl()
        processor = PersonService.Processor(personServiceHandler)
    
        serverSocket = TSocket.TServerSocket(host='127.0.0.1',port=8899)
        transportFactory = TTransport.TFramedTransportFactory()
        protocolFactory = TCompactProtocol.TCompactProtocolFactory()
    
        server = TServer.TSimpleServer(processor,serverSocket,transportFactory,protocolFactory)
        server.serve()
    
    except Thrift.TException as ex:
        print(ex.message)

    注意这里的TServerSocket中的参数不仅要有端口还要有port,并且这里的host如果设置localhost的话

    会提示拒绝连接,所以这使用的是127.0.0.1

    运行Python的服务端,然后再运行Java的客户端

    在Java客户端中调用Python服务端的方法成功。

    示例代码下载

    https://download.csdn.net/download/BADAO_LIUMANG_QIZHI/12869384

    博客园: https://www.cnblogs.com/badaoliumangqizhi/ 关注公众号 霸道的程序猿 获取编程相关电子书、教程推送与免费下载。
  • 相关阅读:
    sql server 阻塞与锁
    JVM监控
    Java性能分析之线程栈详解与性能分析
    MySQL监控调优
    JVM(上)
    性能测试流程介绍
    性能测试分析调优思路
    监控分析——Web中间件
    Linux性能测试工具安装全集
    Java基础(二十)集合(2)Collection接口
  • 原文地址:https://www.cnblogs.com/badaoliumangqizhi/p/13700537.html
Copyright © 2020-2023  润新知