1. 下载Thrift
- thrift-0.9.1.tar.gz
- Thrift compiler for Windows (thrift-0.9.1.exe) : window下编译环境,OS、Linux 需要自己安装编译环境
2. 编写.thrift 文件
- Thrift Types
Base Types: bool ( A boolean value - true or false) , byte ( An 8-bit signed integer ) ,
i16 ( A 16-bit signed integer ) , i32 ( A 32-bit signed integer ) ,
i64 ( A 64-bit signed integer ) , double ( A 64-bit floating point number ) ,
string ( A text string encoded using UTF-8 encoding ) ;
Special Types: binary ( A sequence of unencoded bytes, a specialized form of the
string type above ) ;
Containers: list ( An ordered list of elements, Java ArrayList ) ,
set ( An unordered set of unique elements, Java HashSet ) ,
map ( A map of strictly unique keys to values, Java HashMap );
struct : define a common object ;
exception : 与struct类似,通常定义异常处理类;
service : 相当于定义接口或者抽象类,定义有参数列表、有返回值的方法 ;
- Thrift IDL
Description
Document ::= Header* Definition*
( 0 or more headers followed by 0 or more definitions )
Header ::= Include | CppInclude | Namespace
( a Thrift include / a C++ include / a namespace declaration )
Include : 导入其他thrift文件 ( e. include "shared.thrift" )
Namespace : 根据目标语言指定namespace, package, 或 prefix,
目标语言-'*' | 'cpp' | 'java' | 'py' | 'perl' | 'rb' | 'cocoa' | 'csharp'
(e. namespace java org.apache.thrift 目标语言java,指定包名)
Definition ::= Const | Typedef | Enum | Senum | Struct | Union | Exception | Service
Const ::= 'const' FieldType Identifier '=' ConstValue ListSeparator?
定义全局常量 ( e. const i32 INT32CONSTANT = 9853 )
Typedef : 定义类型别名 ( e. typedef i32 MyInteger)
Enum ::= 'enum' Identifier '{' (Identifier ('=' IntConstant)? ListSeparator?)* '}'
定义枚举类型,值类型i32,值可选,默认值生成器从1开始,无负数
Struct ::= 'struct' Identifier 'xsd_all'? '{' Field* '}' 定义对象
Union ::= 'union' Identifier 'xsd_all'? '{' Field* '}' 类似Struct, 类似C++ union {} in .
Exception ::= 'exception' Identifier '{' Field* '}' 类似Struct,通常定义异常处理机制
Service ::= 'service' Identifier ( 'extends' Identifier )? '{' Function* '}'
定义一组服务接口,service可继承service
------------------------------------------
上述表达式说明:
Field ::= FieldID? FieldReq? FieldType Identifier ('= ConstValue)? ListSeparator?
( e. 1: i32 num1 = 0,)
FieldID ::= IntConstant ':'
FieldReq ::= 'required' | 'optional'
Function ::= 'oneway'? FunctionType Identifier '(' Field* ')' Throws? ListSeparator?
( e. i32 add(1:i32 num1, 2:i32 num2),)
FunctionType ::= FieldType | 'void'
Throws ::= 'throws' '(' Field* ')'
'oneway' 表示客户端请求无须等待响应,返回值必须是void. (e. oneway void zip() )
FieldType ::= Identifier | BaseType | ContainerType
DefinitionType ::= BaseType | ContainerType
BaseType ::= 'bool' | 'byte' | 'i16' | 'i32' | 'i64' | 'double' | 'string' | 'binary' | 'slist'
ContainerType ::= MapType | SetType | ListType
MapType ::= 'map' CppType? '<' FieldType ',' FieldType '>'
SetType ::= 'set' CppType? '<' FieldType '>'
ListType ::= 'list' '<' FieldType '>' CppType?
CppType ::= 'cpp_type' Literal
Literal ::= ('"' [^"]* '"') | ("'" [^']* "'")
Identifier ::= ( Letter | '_' ) ( Letter | Digit | '.' | '_' )*
ListSeparator ::= ',' | ';'
Letter ::= ['A'-'Z'] | ['a'-'z']
Digit ::= ['0'-'9']
-----------------------------
实例: tutorial.thrift
namespace java com.test.message//常量const i32 MSG_TYPR = 100//包装类struct Message { 1: i32 userId = 100, 2: i32 toUserId, 3: string data, //relData 不是必须 (optional) 4: optional string relData,}//定义异常处理类exception InvalidException { 1: i32 toUserId, 2: string error}service PushService { //Thrift中不存在重载,也就是方法名不能一样 void send(1:i32 num1, 2:i32 num2, 3:string data, 4:string relDate), void sendByMessage(1:Message message)}
3. 编译.thrift 文件,生成代码
在thrift-0.9.1.exe目录下执行 。 e. thrift-0.9.1.exe --gen java tutorial.thrift
thrift --gen
编译后会生成搭建RPC服务器与客户端有用的的源代码。目录结构:
|-- gen-java| `-- com| `-- test| `-- message| |-- InvalidException.java| |-- Message.java| |-- PushService.java| `-- transferConstants.java
4. 编写服务端
首先实现编辑生成的PushService.java 中 PushService.Iface 接口,用于服务端处理服务。
public class PushServiceHandler implements PushService.Iface{ @Override public void send(int num1, int num2, String data, String relDate) throws TException { System.out.println(" --- ServHandler send ---"); System.out.println("userId:" + num1 + ", toUserId:" + num2 + ", data:" + data + ", relDate:" + relDate); } @Override public void sendByMessage(Message message) throws TException { System.out.println(" --- ServHandler sendByMessage ---"); System.out.println(message); }}
然后是Service代码
try { // 处理来自客户端的数据 PushServiceHandler handler = new PushServiceHandler(); PushService.Processorprocessor = new PushService.Processor (handler); TServerTransport serverTransport = new TServerSocket(9090); // 通过Address和Handler封装Service TServer server = new TSimpleServer(new Args(serverTransport).processor(processor)); System.out.println("Starting the simple server..."); server.serve(); // 启动服务 } catch (Exception e) { e.printStackTrace(); }
Client 主要代码
try { //连接服务端 TTransport transport = new TSocket("localhost", 9090); transport.open(); //传输协议,可选JSON : TJSONProtocol 等其他协议 TProtocol protocol = new TBinaryProtocol(transport); //客户端调用接口 PushService.Client client = new PushService.Client(protocol); client.send(100, 10001, "推送信息", "关联内容"); System.out.println("--- Client send ---"); client.sendByMessage(new Message(100, 10001, "推送信息")); System.out.println("--- Client sendByMessage ---"); //关闭连接 transport.close(); } catch (Exception e) { e.printStackTrace(); }
运行Service,等待Client调用;
运行Client,传递数据到Service,等待Service返回数据,处理返回结果,线程结束。
Client:--- Client send ------ Client sendByMessage ---Server: Starting the simple server... --- ServHandler send ---userId:100, toUserId:10001, data:推送信息, relDate:关联内容 --- ServHandler sendByMessage ---Message(userId:100, toUserId:10001, data:推送信息)
5. Protocols, Transports and Servers
Protocols: 支持文本与二进制协议,二进制远优于文本协议,文本协议多用于开发调试。
TBinaryProtocol - 二进制编码
TCompactProtocol - 二进制编码,非常高效,使用Variable-Length Quantity (VLQ) 进行编码
TJSONProtocol - 使用JSON格式进行编码
TSimpleJSONProtocol - 提供只写的JSON编码,适用于脚本解析
TDebugProtocol - 在开发模式中提供可阅读的文本编码 (C++)
transports: 上面protocols定义了"what"-传输什么,而transports定义了"how"-怎样传输
TSocket - 堵塞式I/O进行传输
TFramedTransport - 分块传输,当service端使用非阻塞式服务( TNonblockingServer )的时候使用
TFileTransport - 写入到文件进行传输
TZlibTransport - 采用zlib进行压缩,与其他传输相结合,不提供java实现
servers: 每一个Server只能有一个Service
TSimpleServer - 单线程,标准阻塞式I/O,常用于测试
TThreadPoolServer - 多线程,标准阻塞式I/O
TNonblockingServer - 多线程,非阻塞式I/O ( JAVA实现使用NIO ),传输协议必须用TFramedTransport
参考资料: