简介
Thrift最初由Facebook研发,主要用于各个服务之间的RPC通信,支持跨语言,常用的语言比如C++, Java, Python, PHP, Ruby, Erlang, Perl, Haskell, C#, Cocoa, JavaScript, Node.js, Smalltalk, and OCaml都支持。Thrift是一个典型的CS(客户端/服务端)结构,客户端和服务端可以使用不同的语言开发。既然客户端和服务端能使用不同的语言开发,那么一定就要有一种中间语言来关联客户端和服务端的语言,这种语言就是IDL(Interface Description Language)

thrift使用流程
明确要交互的数据格式和具体的方法,定义出thrift接口描述文件(英文叫做IntefaceDescription File)

调用thrift工具,依据thrift接口文件,生成RPC代码;

你的服务器端程序引用thrift生成的RPC代码,并实现其中的Search动作的逻辑,然后启动监听,等待客户端发来请求。
客户端同样引入并调用RPC代码来与服务器端通信

thrift IDL
1. 基本类型
thrift不支持无符号类型,因为很多编程语言不存在无符号类型,比如java

bool: 布尔类型(True or False)
byte: 有符号字节
i16: 16位有符号整数
i32: 32位有符号整数
i64: 64位有符号整数
double: 64位浮点数
string: 字符串
2. 容器类型
集合中的元素可以是除了service之外的任何类型,包括exception。

list <T> : 一系列由T类型的数据组成的有序列表,元素可以重复。会被转换成C++中的vector,Java中的ArrayList,脚本语言中的数组等。
set<T>: 一系列由T类型的数据组成的无序集合,元素不可重复。会转换成C++中的set,Java中的HashSet、Python中的Set等
map<K,V>: 一个字典结构,key为K类型,value为V类型,相当于Java中的HMap

3. 结构体

就像C语言一样,thrift也支持struct类型,目的就是将一些数据聚合在一起,方便传输管理。struct的定 义形式如下:

  1. struct People {
  2. : required string name;
  3. : required i32 age = ;
  4. : optional string sex;
  5. }

可以看到,结构体中每一个域都有一个正整数标识符,这个标识符并不要求连续,但一旦定义,不建议再进行修改
另外,每个域前都会有required或optional的限定,前者表示是必填域,后者则表示是可选域。域是可以有默认值的,比如上例中的“age”。
如果一个域设置为optional且在构造结构体时没有给这个域赋值,那么在使用这个结构体时,就会忽略掉这个optional的域

异常(exception)

thrift支持自定义exception,规则和struct一样,如下:

  1. exception RequestException {
  2. : i32 code;
  3. : string reason;
  4. }

除了使用exception来替代struct以外,“异常”这个类型,在语法上和刚才介绍过的结构体的用法是完全一致的。但是从语义上讲,exception和struct却大相径庭。exception是在远程调用发生异常时用来抛出异常用的

服务(Service)
服务的定义,与面向对象技术中定义一个接口很类似,而这些接口其实就是纯虚函数。thrift编译工具会根据服务的定义来产生相应的方法和函数。
每个服务,都包括了若干个函数,每个函数包括了若干参数和一个返回值(返回值可以是void.
(小技巧:返回值为void的函数,你可以在函数名前加上oneway标识符,将此函数以异步模式执行,这样在调用此函数后,函数会立即返回。)

对于返回void的函数,thrift仍然会确保函数返回,这样就表示这个函数已被正确执行,且服务器端已有返回信息了。但是如果给void的函数前加上oneway,那么此函数的返回只能表示数据已经进入传输层,并不能表示服务器端已经收到并返回了数据

  1. service vulgar_detect{
  2. bool is_vulgar(:string title),
  3. i32 calc(: i32 num)
  4. }

thrift编译工具

在我们编写好thrift接口描述文件之后,thrift编译工具就要派上用场了,它的作用就是根据thrift接口描述文件来生成相应开发语言的RPC代码. 
在终端下输入:

  1. thrift --gen ${开发语言} ${thrift接口描述文件}

Transport

Transport网络读写(socket,http等)抽象,用于和其他thrift组件解耦。
Transport的接口包括:open, close, read, write, flush, isOpen, readAll。
Server端需要ServerTransport(对监听socket的一种抽象),用于接收客户端连接,接口包括:listen, accept, close。
python中Transport的实现包括:TSocket, THttpServer, TSSLSocket, TTwisted, TZlibTransport,都是对某种协议或框架的实现。还有两个装饰器,用于为已有的Transport添加功能,TBufferedTransport(增加缓冲)和TFramedTransport(添加帧)。
在创建server时,传入的时Tranport的工厂,这些Factory包括:TTransportFactoryBase(没有任何修饰,直接返回),TBufferedTransportFactory(返回带缓冲的Transport)和TFramedTransportFactory(返回帧定位的Transport)。

Protocol

Protocol用于对数据格式抽象,在rpc调用时序列化请求和响应。
TProtocol的实现包括:TJSONProtocol,TSimpleJSONProtocol,TBinaryProtocol,TBinaryPotocolAccelerated,TCompactProtocol。

Processor

Processor对stream读写抽象,最终会调用用户编写的handler以响应对应的service。具体的Processor有compiler生成,用户需要实现service的实现类。

Server

Server创建Transport,输入、输出的Protocol,以及响应service的handler,监听到client的请求然后委托给processor处理。
TServer是基类,构造函数的参数包括:
1) processor, serverTransport
2) processor, serverTransport, transportFactory, protocolFactory
3) processor, serverTransport, inputTransportFactory, outputTransportFactory, inputProtocolFactory, outputProtocolFactory
TServer内部实际上需要3)所列的参数,1)和2)会导致对应的参数使用默认值。
TServer的子类包括:TSimpleServer, TThreadedServer, TThreadPoolServer, TForkingServer, THttpServer, TNonblockingServer, TProcessPoolServer
TServer的serve方法用于开始服务,接收client的请求。

Code generated

constants.py: 包含声明的所有常量
ttypes.py: 声明的struct,实现了具体的序列化和反序列化
SERVICE_NAME.py: 对应service的描述文件,包含了:
Iface: service接口定义
Client: client的rpc调用桩

用法

Thrift的用法实际上很简单,定义好IDL,然后实现service对应的handler(方法名、参数列表与接口定义一致接口),最后就是选择各个组件。需要选择的包括:Transport(一般都是socket,只是十分需要选择buffed和framed装饰器factory),Protocol,Server。

IDL文件

  1. /*
  2. thrift接口定义文件
  3. */
  4. service HelloService {
  5. string say(1:string msg)
  6. }

在编辑好定义文件后, 运行如下命令,生成thrift文件。可把hello目录移到当前目录下,便于后面调用。

  1. thrift -r -gen py hello.thrift

server

  1. # coding: utf-8
  2. """
  3. thrift_client.py
  4. """
  5. import socket
  6. import sys
  7. from hello import HelloService
  8. from hello.ttypes import *
  9.  
  10. from thrift.transport import TSocket
  11. from thrift.transport import TTransport
  12. from thrift.protocol import TBinaryProtocol
  13. from thrift.server import TServer
  14.  
  15. class HelloServiceHandler:
  16. def say(self, msg):
  17. ret = "Received: " + msg
  18. print ret
  19. return ret
  20.  
  21. handler = HelloServiceHandler()
  22. processor = HelloService.Processor(handler)
  23. transport = TSocket.TServerSocket("localhost", 9090)
  24. tfactory = TTransport.TBufferedTransportFactory()
  25. pfactory = TBinaryProtocol.TBinaryProtocolFactory()
  26.  
  27. server = TServer.TSimpleServer(processor, transport, tfactory, pfactory)
  28.  
  29. print "Starting thrift server in python..."
  30. server.serve()
  31. print "done!"

client

  1. # coding: utf-8
  2. """
  3. thrift_client.py
  4. """
  5.  
  6. import sys
  7. from hello import HelloService
  8.  
  9. from thrift import Thrift
  10. from thrift.transport import TSocket
  11. from thrift.transport import TTransport
  12. from thrift.protocol import TBinaryProtocol
  13.  
  14. try:
  15. transport = TSocket.TSocket('localhost', 9090)
  16. transport = TTransport.TBufferedTransport(transport)
  17. protocol = TBinaryProtocol.TBinaryProtocol(transport)
  18. client = HelloService.Client(protocol)
  19. transport.open()
  20.  
  21. print "client - say"
  22. msg = client.say("Hello!")
  23. print "server - " + msg
  24.  
  25. transport.close()
  26.  
  27. except Thrift.TException, ex:
  28. print "%s" % (ex.message)

小结

本文只是一个简单的示例,在实际项目中,一般会基于zookeeper来注册和管理服务的thrift状态,并对server和client进一步封装,便于在项目各个模块中调用。

python thrift demo的更多相关文章

  1. Python Thrift 简单示例

    本文基于Thrift-0.10,使用Python实现服务器端,使用Java实现客户端,演示了Thrift RPC调用示例.Java客户端提供两个字符串参数,Python服务器端计算这两个字符串的相似度 ...

  2. python thrift使用实例

    前言 Apache Thrift 是 Facebook 实现的一种高效的.支持多种编程语言的远程服务调用的框架.本文将从 Python开发人员角度简单介绍 Apache Thrift 的架构.开发和使 ...

  3. python thrift 实现 单端口多服务的过程

    Thrift 是一种接口描述语言和二进制通信协议.以前也没接触过,最近有个项目需要建立自动化测试,这个项目之间的微服务都是通过 Thrift 进行通信的,然后写自动化脚本之前研究了一下. 需要定义一个 ...

  4. python thrift 服务端与客户端使用

    一.简介 thrift是一个软件框架,用来进行可扩展且跨语言的服务的开发.它结合了功能强大的软件堆栈和代码生成引擎,以构建在 C++, Java, Python, PHP, Ruby, Erlang, ...

  5. python supervisor demo deployment

    I did a demo about how to deploy other python apps served by a 'supervisord' daemon processor on git ...

  6. win7环境下,golang thrift demo代码编译不通过

    用官方的教程代码:http://thrift.apache.org/tutorial/go 用网友提供的代码:Golang RPC 之 Thrift 都出现如下情况 状况1: 编辑器中就会提醒 Can ...

  7. RSA签名 python PHP demo 例子

    python RSA+MD5签名demo: #!/usr/bin/env python2.7 #coding:utf-8 import base64 from Crypto.PublicKey imp ...

  8. python thrift hbase安装连接

    默认已装好 hbase,我的版本是hbase-0.98.24,并运行 python 2.7.x 步骤: sudo apt-get install automake bison flex g++ git ...

  9. C# Apache Thrift Demo

    转载至 https://headsigned.com/posts/csharp-apache-thrift-demo/ This demo application shows how to imple ...

随机推荐

  1. iptable实现端口转发

    利用iptables的规则来实现端口转发: 第一步需要将内核参数的net.ipv4.ip_forward=1 场景一:实现本地端口转发 本地端口转发实在PREROUTING链中将端口做NAT转换: # ...

  2. 032-session函数

    <?php $username="guest1"; if(isset($username)) { session_name($username); } echo " ...

  3. 105-PHP使用var_dump查看类的类型

    <?php class ren{ //定义人类 } class mao{ //定义猫类 } $ren1=new ren(); //实例化人类 $mao1=new mao(); //实例化猫类 $ ...

  4. React 学习笔记(3) B站视频总结1

    视频地址 项目基础 react-cli // 项目结构 src │ App.js # 应用根组件 │ index.js # 入口js ├─api ├─assets ├─components ├─con ...

  5. ELK 教程

    自从ELK首次推出以来,下载量达到了数百万次,是世界上最流行的日志管理平台.相比之下,Splunk - 该领域的历史领先者 - 宣布的客户总数才15000人. 章节 ELK 介绍 ELK 安装Elas ...

  6. C# Stream篇(四) -- FileStream

    FileStream 目录: 如何去理解FileStream? FileStream的重要性 FileStream常用构造函数(重要) 非托管参数SafeFileHandle简单介绍 FileStre ...

  7. POJ-3984 迷宫问题(BFS找最短路径并保存)

    问题: 定义一个二维数组:  int maze[5][5] = { 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, ...

  8. UVA - 11212 Editing a Book(IDA*算法+状态空间搜索)

    题意:通过剪切粘贴操作,将n个自然段组成的文章,排列成1,2,……,n.剪贴板只有一个,问需要完成多少次剪切粘贴操作可以使文章自然段有序排列. 分析: 1.IDA*搜索:maxn是dfs的层数上限,若 ...

  9. filter滤镜兼容ie的rgba属性

    要在一个页面中设置一个半透明的白色div.这个貌似不是难题,只需要给这个div设置如下的属性即可: background: rgba(255,255,255,0.1); 但是要兼容到ie8.这个就有点 ...

  10. 对于AVL树和红黑树的理解

    AVL又称(严格)高度平衡的二叉搜索树,也叫二叉查找树.平衡二叉树.window对进程地址空间的管理用到了AVL树. 红黑树是非严格平衡二叉树,统计性能要好于平衡二叉树.广泛的在C++的STL中,ma ...