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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM