什么是Thrift
Apache Thrift 是 Facebook 实现的一种高效的、支持多种编程语言的远程服务调用的框架。
它采用接口描述语言定义并创建服务,支持可扩展的跨语言服务开发,所包含的代码生成引擎可以在多种语言中,如 C++, Java, Python, PHP, Ruby, Erlang, Perl, Haskell, C#, Cocoa, Smalltalk 等创建高效的、无缝的服务,其传输数据采用二进制格式,相对 XML 和 JSON 体积更小,对于高并发、大数据量和多语言的环境更有优势。
简单来说,是Facebook公布的一款开源跨语言的RPC框架.
什么是RPC
- RPC全称为Remote Procedure Call,意为远程过程调用.
- 假设有两台服务器A,B.A服务器上部署着一个应用a,B服务器上部署着一个应用b,现在a希望能够调用b应用的某个函数(方法),但是二者不在同一个进程内,不能直接调用,就需要通过网络传输,在AB服务器之间建一条网络传输通道,a把参数传过去,b接收到参数调用自己的方法,得到结果,再通过网络传回给a,简单讲就是A通过网络来调用B的过程.这个过程要涉及的东西很多,比如多线程,Socket,序列化反序列化,网络I/O,很复杂,于是牛掰的程序员把这些封装起来做成一套框架,供大家使用,就是RPC框架.
Thrift的跨语言特性
- thrift通过一个中间语言IDL(接口定义语言)来定义RPC的数据类型和接口,这些内容写在以.thrift结尾的文件中,然后通过特殊的编译器来生成不同语言的代码,以满足不同需要的开发者,比如java开发者,就可以生成java代码,c++开发者可以生成c++代码,生成的代码中不但包含目标语言的接口定义,方法,数据类型,还包含有RPC协议层和传输层的实现代码.
Thrift的协议栈结构
- thrift是一种c/s的架构体系.在最上层是用户自行实现的业务逻辑代码.第二层是由thrift编译器自动生成的代码,主要用于结构化数据的解析,发送和接收。TServer主要任务是高效的接受客户端请求,并将请求转发给Processor处理。Processor负责对客户端的请求做出响应,包括RPC请求转发,调用参数解析和用户逻辑调用,返回值写回等处理。从TProtocol以下部分是thirft的传输协议和底层I/O通信。TProtocol是用于数据类型解析的,将结构化数据转化为字节流给TTransport进行传输。TTransport是与底层数据传输密切相关的传输层,负责以字节流方式接收和发送消息体,不关注是什么数据类型。底层IO负责实际的数据传输,包括socket、文件和压缩数据流等。
Thrift实现-nodejs与python之间通信
- 官网下载安装Thrift
- RPC的通信原理
2.1 双方持有共同的接口存根(接口定义)
2.2 Server端实现具体的接口实现类。
2.3 Client通过动态代理,封装网络通讯过程,发送调用接口名称和参数到Server端。
2.4 Server将处理结果返回Client。
3. Thrift基础
3.1 Thrift基本数据类型:
3.2 结构:
3.3 service 定义的接口存根(返回类型,方法名,参数):
3.4 定义完接口存根后,利用thrift生成相应的接口文件:
thrift -out 存储路径 --gen 接口语言 thrift 文件名
python栗子 thrift -r -gen py pyTest.thrift
nodejs栗子 thrift --gen js:node pyTest.thrift
3.5 生成的相应接口文件概览:
生成的gen-py: init.py,pyTest
生成的gen-nodejs:
3.6 在server端编写相应的接口方法
接口定义为:
利用Thrift生成接口文件后编写python server端 来实现定义的接口存根
Python引入Thrift 方式: pip install thrift
import sys
import json
import configparser
sys.path.append("./gen-py")
from pyTest import HadoopService
from impala.dbapi import connect
from thrift.transport import TSocket
from thrift.transport import TTransport
from thrift.protocol import TBinaryProtocol
from thrift.server import TServer
cf = configparser.ConfigParser()
cf.read("conf/config.conf")
class HadoopServiceHandler:
def connectHadoop(self,msg):
data = json.loads(msg)
self.conn = connect(host=data["host"],port=data["port"],
database=data["database"],auth_mechanism=data["auth_mechanism"]
)
sql = "show tables"
cursor = self.conn.cursor()
cursor.execute(sql)
tables = cursor.fetchall()
tableList = [