1/thrift简介
thrift最初是由facebook公司开发的开源的,跨平台的,跨语言的rpc框架。
(rpc框架是一个统称,包括很多具体的框架,比如谷歌开发的grpc框架,facebook开发的thrift框架)
现在facebook公司已经把thrift框架贡献给了apache基金会。
2/安装thrift
如果你是在mac上安装,可以使用命令 brew install thrift 来安装。
(前提是你已经安装了homebrew这个mac特有的包管理工具了)
如果你没有安装brew,当你brew install thrift的时候,会提示:
command not found: brew,
则你需要先安装homebrew。
如何安装homebrew,可以参考:
https://juejin.cn/post/6982513337716178980/
<1>安装thrift
brew install thrift
这个安装过程的时间可能会比较长,请耐心等待。
默认是安装在/usr/local/Cellar目录下的(brew安装的东西,默认都是安装在Cellar这个目录下的)
<2>配置环境变量(把thrift的bin目录下的可执行文件加入到环境变量)
vim .bash_profile
export PATH=$PATH:/usr/local/Cellar/thrift/0.16.0/bin
source .bash_profile
这样thrift的环境变量就是配置好了,且立即生效了。
<3>查看thrift的版本,确定是否安装成功
thrift --version 或者thrift -version 都可以,及一个'-'或者两个'--'都是可以的。
如果显示thrift的版本号,则代表thrift已经安装完成了。
3/服务端
如果使用thrift框架来调用别人的服务,则必须要知道别人写的.thrift文件.
.thrift文件,其实就是你要访问的服务的一份说明书,里面会定义服务的名称,以及该服务中的函数,以及函数的入参有几个,每个参数的数据类型是什么,参数的名称是啥,还有返回值的数据类型。
<1>编写.thrift文件,以及生成一个目录,该目录包含所依赖的东西
如果是你自己要开发一个服务供别人来调用,那么你需要写一个.thrift文件
.thrift文件是用IDL语言来写的,用
下面以evasion.thrift文件为例(evasion是逃单的意思)
namespace py dependence
service Evasion {
string say_hello(1:string what),
double cal_sum_value(1:i64 n1, 2:i64 n2),
double similarity(1:string chat1, 2:string chat2)
}
编写完evasion.thrift文件之后,运行thrift --gen py evasion.thrift 或者 thrift -gen py evasion.thrift ,这2条命令都可以,-gen 或者 --gen 都可以
会在evasion.thrift文件的同一级目录下生成一个gen-py的目录,该目录下还有别的层级。
具体是什么层级,和你.thrift文件中的namespace的设置有关。
然后对gen-py目录进行重命名(当然也可以不重命名,只要你能分清楚即可)
<2>服务端开发
以下是python开发服务的方式
import sys
sys.path.append('./gen-py')
from thrift.transport import TSocket
from thrift.protocol import TBinaryProtocol
from thrift.server import TServer
from dependence.Evasion import *
from dependence.ttypes import *
class EvasionHandler:
def say_hello(self, what):
print('say_hello is called......,param is {}'.format(what))
return "hello %s" % what
def cal_sum_value(self, n1, n2):
print('cal_sum_value is called......,param is {} and {}'.format(n1, ne2))
if n1 >= n2:
return n1
else:
return n2
def similarity(self, chat1, chat2):
print("similarity is called......, param is {} and {}".format(chat1, chat2))
result = xxx
return result
def func_server_start():
handler = HelloHandler()
processor = Processor(handler)
transport = TSocket.TServerSocket('localhost', 9234)
pfactory = TBinaryProtocol.TBinaryProtocolFactory()
tfactory = TTransport.TBufferedTransportFactory()
server = TServer.TThreadPoolServer(processor,
transport,
tfactory,
pfactory)
server.setNumThreads(5)
print("server is running。。。。。")
server.serve()
if __name__ == '__main__':
func_server_start()
4/客户端
在客户端,如果想调用远程的服务
需要先把别人的.thrift文件拿到,然后通过thrift --gen py xxx.thrift命令在本地生成python的代码。
from thrift import Thrift
from thrift.transport import TSocket, TTransport
from thrift.protocol import TBinaryProtocol
import sys
sys.path.append('./gen-py')
from dependents.HelloWhat import *
def func_cli():
try:
transport = TSocket.TSocket('localhost', 9234)
transport = TTransport.TBufferedTransport(transport)
protocal = TBinaryProtocol.TBinaryProtocol(transport)
client = Client(protocal)
transport.open()
res1 = client.say_hello("thrift")
res2 = client.cal_sum_value(10, 20)
print(res1)
print(res2)
transport.close()
except Exception as err:
print(err)
if __name__ == "__main__":
func_cli()
5/使用thriftpy
thriftpy这个第三方包(现在已经更新为thriftpy2)对thrift进行了封装,可以动态解析thrift的接口文件。
5.1/安装thriftpy2
pip install thriftpy2
5.2/编写IDL文件
pingpong.thrift
service PingService {
string ping(),
}
service AargsPingService {
string ping(1:string ping);
}
service Sleep {
oneway void sleep(1: i32 seconds)
}
5.3/服务端开发
import thriftpy2
from thriftpy2.rpc import make_server
pp_thrift = thriftpy2.load("pingpong.thrift", module_name="pp_thrift")
class Dispatcher(object):
def ping(self):
print("ping pong!")
return 'pong'
def main():
server = make_server(pp_thrift.PingService, Dispatcher(), '127.0.0.1', 6000)
print("serving...")
server.serve()
if __name__ == '__main__':
main()
5.4/客户端开发
import thriftpy2
from thriftpy2.rpc import make_client
pp_thrift = thriftpy2.load("pingpong.thrift", module_name="pp_thrift")
def main():
client = make_client(pp_thrift.PingService, '127.0.0.1', 6000)
result = client.ping()
print(result)
if __name__ == '__main__':
main()