1、Thrift简介
Thrift是一个跨语言的服务部署框架,最初由Facebook于2007年开发,2008年进入Apache开源项目。Thrift通过一个中间语言(IDL, 接口定义语言)来定义RPC的接口和数据类型,然后通过一个编译器生成不同语言的代码(目前支持C++,Java, Python, PHP, Ruby, Erlang, Perl, Haskell, C#, Cocoa,Smalltalk和OCaml),并由生成的代码负责RPC协议层和传输层的实现。
主要分为六个部分1.你的业务逻辑实现(You Code) 2.客户端和服务端对应的Service 3.执行读写操作的计算结果4.TProtocol5.TTransports 6.底层I/O通信。
2、Thrift语法
参考董的博客,地址:http://dongxicheng.org/search-engine/thrift-guide/
3、基本知识简介
来源网址:http://www.javabloger.com/article/apache-thrift-architecture.html
a)数据类型
* Base Types:基本类型
* Struct:结构体类型
* Container:容器类型,即List、Set、Map
* Exception:异常类型
* Service: 定义对象的接口,和一系列方法
b)协议
Thrift可以让你选择客户端与服务端之间传输通信协议的类别,在传输协议上总体上划分为文本(text)和二进制(binary)传输协议, 为节约带宽,提供传输效率,一般情况下使用二进制类型的传输协议为多数,但有时会还是会使用基于文本类型的协议,这需要根据项目/产品中的实际需求:
*TBinaryProtocol – 二进制编码格式进行数据传输。
*TCompactProtocol – 这种协议非常有效,使用Variable-Length Quantity (VLQ) 编码对数据进行压缩。
*TJSONProtocol – 使用JSON的数据编码协议进行数据传输。
*TSimpleJSONProtocol – 这种节约只提供JSON只写的协议,适用于通过脚本语言解析
*TDebugProtocol – 在开发的过程中帮助开发人员调试用的,以文本的形式展现方便阅读。
c)传输层
*TSocket- 使用堵塞式I/O进行传输,也是最常见的模式。
*TFramedTransport- 使用非阻塞方式,按块的大小,进行传输,类似于Java中的NIO。
*TFileTransport- 顾名思义按照文件的方式进程传输,虽然这种方式不提供Java的实现,但是实现起来非常简单。
*TMemoryTransport- 使用内存I/O,就好比Java中的ByteArrayOutputStream实现。
*TZlibTransport- 使用执行zlib压缩,不提供Java的实现。
d)服务端类型
*TSimpleServer - 单线程服务器端使用标准的堵塞式I/O。
*TThreadPoolServer - 多线程服务器端使用标准的堵塞式I/O。
*TNonblockingServer – 多线程服务器端使用非堵塞式I/O,并且实现了Java中的NIO通道。
e)Thrift与其他传输方式的比较
xml与JSON相比体积太大,但是xml传统,也不算复杂。
json 体积较小,新颖,但不够完善。
thrift 体积超小,使用起来比较麻烦,不如前两者轻便,但是对于1.高并发、2.数据传输量大、3.多语言环境, 满足其中2点使用 thrift还是值得的。
4.Thrift DEMO
参考网址:http://www.micmiu.com/soa/rpc/thrift-sample/
第一步,编写thrift内容 这里主要是定义接口
DemoHello.thrift内容:
namespace java com.lza.thrift
service HelloWorldService{
stringsayHello(1:string username)
}
第二步,利用thrift编译工具将thrift文本编译成对应语言的文本,这里编译为JAVA。WINDOWS下的编译工具为thrift-0.8.0.exe
命令格式:thrift-0.8.0.exe-r -gen java ./DemoHello.thrift
这样就会在thrfit-0.8.0.exe所在目录下生成一个文件夹,如图一所示。
(图一)
第三步,进行服务端和客户端编程。
生成的HelloWorldService.java文件一般不要去修改,除非你已经清楚的知道原理。这个文件中主要是提供了一些服务端和客户端进行交互的接口,并提供同步和异步两种接口。
1)服务端编码的基本步骤:
实现服务处理接口impl
创建TProcessor
创建TServerTransport
创建TProtocol
创建TServer
启动Server
2)客户端编码基本步骤:
创建Transport
创建TProtocol
基于TTransport和TProtocol创建 Client
调用Client的相应方法
3)接口实现代码:
package com.lza.thrift;
import org.apache.thrift.TException;
import com.lza.thrift.HelloWorldService;
/**
* 实现接口
* @author Administrator
*
*/
public class HelloWorldImpl implements HelloWorldService.Iface {
/**
* 根据传入的用户名向用户问好
*/
@Override
public String sayHello(String username) throws TException {
// TODO Auto-generated method stub
String resultStr="Hi,"+"Welcome to our company !"+username;
return resultStr;
}
}
4)服务端代码:
package com.lza.thrift;
import org.apache.thrift.TProcessor;
import org.apache.thrift.protocol.TBinaryProtocol;
import org.apache.thrift.server.TServer;
import org.apache.thrift.server.TSimpleServer;
import org.apache.thrift.transport.TServerSocket;
import com.lza.thrift.HelloWorldService;
import com.lza.thrift.HelloWorldImpl;
/**
* 编写服务端代码
* @author Administrator
*
*/
public class HelloWorldServerDemo {
public static final int SERVER_PORT=8090;
/**
* 启动服务函数
*/
public void startServe(){
try{
System.out.println("Hello World TSimpleServer start....");
/**
* 通过接口实现类去实例化数据流接口
* TProcessor接口的功能是封装了数据流的读写操作 读写数据流用Protocol对象表示
* TProcessor接口结构
* interface TProcessor{
* bool process(TProtocol in,TProtocol out) throws TException
* }
*/
TProcessor tpprocessor=new HelloWorldService.Processor(new HelloWorldImpl());
/**
* 实例化服务端口
*/
TServerSocket serverTransport=new TServerSocket(SERVER_PORT);
/**
* 创建TServer参数对象
*/
TServer.Args tArgs=new TServer.Args(serverTransport);
/**
* 指定数据流读写对象
*/
tArgs.processor(tpprocessor);
/**
* 指定数据传输协议为二进制
*/
tArgs.protocolFactory(new TBinaryProtocol.Factory());
/**
* 创建服务对象 单线程用TSimpleServer 多线程用TNonblockingServerSocket或者TThreadPoolServer
*/
TServer server=new TSimpleServer(tArgs);
/**
* 调用thrift生成JAVA文件中的serve()函数
*/
server.serve();
}catch(Exception e){
System.out.println("Server start error!!");
e.printStackTrace();
}
}
public static void main(String args[]){
HelloWorldServerDemo server=new HelloWorldServerDemo();
server.startServe();
}
}
5)客户端代码:
package com.lza.thrift;
import org.apache.thrift.protocol.TBinaryProtocol;
import org.apache.thrift.protocol.TProtocol;
import org.apache.thrift.transport.TSocket;
import org.apache.thrift.transport.TTransport;
/**
* 客户端代码编写
* @author Administrator
*
*/
public class HelloWorldClientDemo {
public static final String SERVER_IP="localhost";
public static final int SERVER_PORT=8090;
public static final int TIMEOUT=30000;
/**
* 客户端实现函数
* @param username 传入的用户名称
*/
public void startClient(String username){
/**
* 创建传输对象
*/
TTransport transport=null;
try{
/**
* 根据服务端地址、服务端口、超时限制等参数实现化传输类TSocket
* 详细解析参考:http://blog.csdn.net/qiangweiloveforever/article/details/9474941
* 传输方式必须与服务端一致
*/
transport=new TSocket(SERVER_IP,SERVER_PORT,TIMEOUT);
/**
* 设定传输协议 必须和服务端一致
*/
TProtocol protocol=new TBinaryProtocol(transport);
/**
* 实例化客户端对象
*/
HelloWorldService.Client client=new HelloWorldService.Client(protocol);
/**
* 与服务端开始传输通信
*/
transport.open();
/**
* 通过客户端对象向服务端进行接口调用请求,并返回调用结果
*/
String result=client.sayHello(username);
System.out.println("Thrifty client result="+result);
}catch(Exception e){
e.printStackTrace();
}finally{
if(transport!=null){
transport.close();
}
}
}
public static void main(String args[]){
HelloWorldClientDemo client=new HelloWorldClientDemo();
client.startClient("LZA");
}
}
5.运行结果
运行服务端结果:
运行客户端结果:
测试通过,符合预想。
声明:本文主要来自网上整理 程序代码中的解析为个人理解 如有错误 请指出 欢迎交流