Thrift最初由facebook开发,07年四月开放源码,08年5月进入apache孵化器。thrift允许你定义一个简单的定义文件中的数据类型和服务接口。以作为输入文件,编译器生成代码用来方便地生成RPC客户端和服务器通信的无缝跨编程语言。
官网地址:thrift.apache.org
推荐值得一看的文章:
http://jnb.ociweb.com/jnb/jnbJun2009.html
http://wiki.apache.org/thrift
http://thrift.apache.org/static/files/thrift-20070401.pdf
- Thrift 基础架构
Thrift是一个服务端和客户端的架构体系,就是socket传输,Thrift 具有自己内部定义的传输协议规范(TProtocol)和传输数据标准(TTransports),通过IDL脚本对传输数据的数据结构(struct) 和传输数据的业务逻辑(service)根据不同的运行环境快速的构建相应的代码,并且通过自己内部的序列化机制对传输的数据进行简化和压缩提高高并发、 大型系统中数据交互的成本,下图描绘了Thrift的整体架构,分为6个部分:
1.你的业务逻辑实现(You Code)
2.客户端和服务端对应的Service
3.执行读写操作的计算结果
4.TProtocol
5.TTransports
6.底层I/O通信
- Thrift 软件栈
评注:
Transport: 传输层,定义数据传输方式,可以为TCP/IP传输,内存共享或者文件共享等
protocol: 协议层, 定义数据传输格式,可以为二进制或者XML等
Processor: 处理层, 这部分由定义的idl来生成, 封装了协议输入输出流, 并委托给用户实现的handler进行处理.
Server: 服务层, 整合上述组件, 提供网络模型(单线程/多线程/事件驱动), 最终形成真正的服务.
- Thrift脚本的数据类型
bool Boolean, one byte
byte Signed byte
i16 Signed 16-bit integer
i32 Signed 32-bit integer
i64 Signed 64-bit integer
double 64-bit floating point value
string String
binary Blob (byte array)
* Struct:结构体类型
* Container:容器类型,即List、Set、Map
map<t1,t2> Map from one type to another
list<t1> Ordered list of one type
set<t1> Set of unique elements of one type
* Exception:异常类型
* Service: 定义对象的接口,和一系列方法
- 协议
* TBinaryProtocol – 二进制编码格式进行数据传输。
* TCompactProtocol – 这种协议非常有效的,使用Variable-Length Quantity (VLQ) 编码对数据进行压缩。
* TJSONProtocol – 使用JSON的数据编码协议进行数据传输。
* TSimpleJSONProtocol – 这种节约只提供JSON只写的协议,适用于通过脚本语言解析
* TDebugProtocol – 在开发的过程中帮助开发人员调试用的,以文本的形式展现方便阅读。
- 传输层
* TFramedTransport- 使用非阻塞方式,按块的大小,进行传输,类似于Java中的NIO。
* TFileTransport- 顾名思义按照文件的方式进程传输,虽然这种方式不提供Java的实现,但是实现起来非常简单。
* TMemoryTransport- 使用内存I/O,就好比Java中的ByteArrayOutputStream实现。
* TZlibTransport- 使用执行zlib压缩,不提供Java的实现。
- Thrift 高性能网络服务模型
TSimpleServer/TThreadPoolServer是阻塞服务模型
TNonblockingServer/THsHaServer/TThreadedSelectotServer是非阻塞服务模型(NIO)
2). TServer抽象类的定义
内部静态类Args的定义, 用于TServer类用于串联软件栈(传输层, 协议层, 处理层)
public abstract class TServer {
public static class Args extends AbstractServerArgs<Args> {
public Args(TServerTransport transport) {
super(transport);
}
}
public static abstract class AbstractServerArgs<T extends AbstractServerArgs<T>> {
public AbstractServerArgs(TServerTransport transport);
public T processorFactory(TProcessorFactory factory);
public T processor(TProcessor processor);
public T transportFactory(TTransportFactory factory);
public T protocolFactory(TProtocolFactory factory);
}
}
TServer类定义的抽象类
public abstract class TServer {
public abstract void serve();
public void stop();
public boolean isServing();
public void setServerEventHandler(TServerEventHandler eventHandler);
}
评注:抽象函数serve由具体的TServer实例来实现, 而并非所有的服务都需要优雅的退出, 因此stop没有被定义为抽象。
各种服务模型介绍如下:
* TSimpleServer - 单线程服务器端使用标准的堵塞式I/O,只适合测试开发使用。抽象代码描述如下:
// *) server socket进行监听
serverSocket.listen();
while ( isServing() ) {
// *) 接受socket链接
client = serverSocket.accept();
// *) 封装处理器
processor = factory.getProcess(client);
while ( true ) {
// *) 阻塞处理rpc的输入/输出
if ( !processor.process(input, output) ) {
break;
}
}
}
* TThreadPoolServer - 多线程服务器端使用标准的堵塞式I/O。引入了线程池,实现的模型是One Thread Per Connection。
线程池代码片段如下:
private static ExecutorService createDefaultExecutorService(Args args) {
SynchronousQueue<Runnable> executorQueue =
new SynchronousQueue<Runnable>();
return new ThreadPoolExecutor(args.minWorkerThreads,
args.maxWorkerThreads,
60,
TimeUnit.SECONDS,
executorQueue);
}
采用同步队列(SynchronousQueue), 线程池采用能线程数可伸缩的模式.
主线程循环:
setServing(true);
while (!stopped_) {
try {
TTransport client = serverTransport_.accept();
WorkerProcess wp = new WorkerProcess(client);
executorService_.execute(wp);
} catch (TTransportException ttx) {
}
}
拆分了监听线程(accept)和处理客户端连接的工作线程(worker), 监听线程每接到一个客户端, 就投给线程池去处理. 这种模型能提高并发度, 但并发数取决于线程数, IO依旧阻塞, 从而限制该服务的服务能力。
* TNonblockingServer – 采用NIO的模式, 借助Channel/Selector机制, 采用IO事件模型来处理。
private void select() {
try {
selector.select(); // wait for io events.
// process the io events we received
Iterator<SelectionKey> selectedKeys = selector.selectedKeys().iterator();
while (!stopped_ && selectedKeys.hasNext()) {
SelectionKey key = selectedKeys.next();
selectedKeys.remove();
if (key.isAcceptable()) {
handleAccept(); // deal with accept
} else if (key.isReadable()) {
handleRead(key); // deal with reads
} else if (key.isWritable()) {
handleWrite(key); // deal with writes
}
}
} catch (IOException e) {
}
}
select代码里对accept/read/write等IO事件进行监控和处理, 唯一可惜的这个单线程处理. 当遇到handler里有阻塞的操作时, 会导致整个服务被阻塞住。
*THsHaServer - 半同步半异步
鉴于TNonblockingServer的缺点, THsHa引入了线程池去处理, 其模型把读写任务放到线程池去处理。HsHa是: Half-sync/Half-async的处理模式, Half-aysnc是在处理IO事件上(accept/read/write io), Half-sync用于handler对rpc的同步处理上.
*TThreadedSelectorServer- 多线程服务器端使用非堵塞式I/O,是对以上NonblockingServer的扩充, 其分离了Accept和Read/Write的Selector线程, 同时引入Worker工作线程池. 它也是种Half-sync/Half-async的服务模型,也是最成熟,也是被业界所推崇的RPC服务模型。
MainReactor就是Accept线程, 用于监听客户端连接, SubReactor采用IO事件线程(多个), 主要负责对所有客户端的IO读写事件进行处理. 而Worker工作线程主要用于处理每个rpc请求的handler回调处理(这部分是同步的)。
- Java简单实例
namespace java cn.slimsmart.thrift.demo.helloworld
service HelloWorld{
string sayHello(1:string username)
}
2.生成java接口文件
/**
* Autogenerated by Thrift Compiler (0.9.2)
*
* DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
* @generated
*/
package cn.slimsmart.thrift.demo.helloworld;
import java.util.ArrayList;
import java.util.BitSet;
import java.util.Collections;
import java.util.EnumMap;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.annotation.Generated;
import org.apache.thrift.TException;
import org.apache.thrift.async.AsyncMethodCallback;
import org.apache.thrift.protocol.TTupleProtocol;
import org.apache.thrift.scheme.IScheme;
import org.apache.thrift.scheme.SchemeFactory;
import org.apache.thrift.scheme.StandardScheme;
import org.apache.thrift.scheme.TupleScheme;
import org.apache.thrift.server.AbstractNonblockingServer.AsyncFrameBuffer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* 通过HelloWord.thrift 生成的接口类
*/
@SuppressWarnings({"cast", "rawtypes", "serial", "unchecked"})
@Generated(value = "Autogenerated by Thrift Compiler (0.9.2)", date = "2015-2-28")
public class HelloWorld {
//同步接口
public interface Iface {
public String sayHello(String username) throws org.apache.thrift.TException;
}
//异步接口
public interface AsyncIface {
public void sayHello(String username, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException;
}
//客户端同步接口实现代理类
public static class Client extends org.apache.thrift.TServiceClient implements Iface {
public static class Factory implements org.apache.thrift.TServiceClientFactory<Client> {
public Factory() {}
public Client getClient(org.apache.thrift.protocol.TProtocol prot) {
return new Client(prot);
}
public Client getClient(org.apache.thrift.protocol.TProtocol iprot, org.apache.thrift.protocol.TProtocol oprot) {
return new Client(iprot, oprot);
}
}
public Client(org.apache.thrift.protocol.TProtocol prot)
{
super(prot, prot);
}
public Client(org.apache.thrift.protocol.TProtocol iprot, org.apache.thrift.protocol.TProtocol oprot) {
super(iprot, oprot);
}
public String sayHello(String username) throws org.apache.thrift.TException
{
send_sayHello(username);
return recv_sayHello();
}
public void send_sayHello(String username) throws org.apache.thrift.TException
{
sayHello_args args = new sayHello_args();
args.setUsername(username);
sendBase("sayHello", args);
}
public String recv_sayHello() throws org.apache.thrift.TException
{
sayHello_result result = new sayHello_result();
receiveBase(result, "sayHello");
if (result.isSetSuccess()) {
return result.success;
}
throw new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.MISSING_RESULT, "sayHello failed: unknown result");
}
}
//客户端异步接口实现代理类
public static class AsyncClient extends org.apache.thrift.async.TAsyncClient implements AsyncIface {
public static class Factory implements org.apache.thrift.async.TAsyncClientFactory<AsyncClient> {
private org.apache.thrift.async.TAsyncClientManager clientManager;
private org.apache.thrift.protocol.TProtocolFactory protocolFactory;
public Factory(org.apache.thrift.async.TAsyncClientManager clientManager, org.apache.thrift.protocol.TProtocolFactory protocolFactory) {
this.clientManager = clientManager;
this.protocolFactory = protocolFactory;
}
public AsyncClient getAsyncClient(org.apache.thrift.transport.TNonblockingTransport transport) {
return new AsyncClient(protocolFactory, clientManager, transport);
}
}
public AsyncClient(org.apache.thrift.protocol.TProtocolFactory protocolFactory, org.apache.thrift.async.TAsyncClientManager clientManager, org.apache.thrift.transport.TNonblockingTransport transport) {
super(protocolFactory, clientManager, transport);
}
public void sayHello(String username, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException {
checkReady();
sayHello_call method_call = new sayHello_call(username, resultHandler, this, ___protocolFactory, ___transport);
this.___currentMethod = method_call;
___manager.call(method_call);
}
public static class sayHello_call extends org.apache.thrift.async.TAsyncMethodCall {
private String username;
public sayHello_call(String username, org.apache.thrift.async.AsyncMethodCallback resultHandler, org.apache.thrift.async.TAsyncClient client, org.apache.thrift.protocol.TProtocolFactory protocolFactory, org.apache.thrift.transport.TNonblockingTransport transport) throws org.apache.thrift.TException {
super(client, protocolFactory, transport, resultHandler, false);
this.username = username;
}
public void write_args(org.apache.thrift.protocol.TProtocol prot) throws org.apache.thrift.TException {
prot.writeMessageBegin(new org.apache.thrift.protocol.TMessage("sayHello", org.apache.thrift.protocol.TMessageType.CALL, 0));
sayHello_args args = new sayHello_args();
args.setUsername(username);
args.write(prot);
prot.writeMessageEnd();
}
public String getResult() throws org.apache.thrift.TException {
if (getState() != org.apache.thrift.async.TAsyncMethodCall.State.RESPONSE_READ) {
throw new IllegalStateException("Method call not finished!");
}
org.apache.thrift.transport.TMemoryInputTransport memoryTransport = new org.apache.thrift.transport.TMemoryInputTransport(getFrameBuffer().array());
org.apache.thrift.protocol.TProtocol prot = client.getProtocolFactory().getProtocol(memoryTransport);
return (new Client(prot)).recv_sayHello();
}
}
}
//服务端同步代理调用处理器
public static class Processor<I extends Iface> extends org.apache.thrift.TBaseProcessor<I> implements org.apache.thrift.TProcessor {
public Processor(I iface) {
super(iface, getProcessMap(new HashMap<String, org.apache.thrift.ProcessFunction<I, ? extends org.apache.thrift.TBase>>()));
}
protected Processor(I iface, Map<String, org.apache.thrift.ProcessFunction<I, ? extends org.apache.thrift.TBase>> processMap) {
super(iface, getProcessMap(processMap));
}
private static <I extends Iface> Map<String, org.apache.thrift.ProcessFunction<I, ? extends org.apache.thrift.TBase>> getProcessMap(Map<String, org.apache.thrift.ProcessFunction<I, ? extends org.apache.thrift.TBase>> processMap) {
processMap.put("sayHello", new sayHello());
return processMap;
}
public static class sayHello<I extends Iface> extends org.apache.thrift.ProcessFunction<I, sayHello_args> {
public sayHello() {
super("sayHello");
}
public sayHello_args getEmptyArgsInstance() {
return new sayHello_args();
}
protected boolean isOneway() {
return false;
}
public sayHello_result getResult(I iface, sayHello_args args) throws org.apache.thrift.TException {
sayHello_result result = new sayHello_result();
result.success = iface.sayHello(args.username);
return result;
}
}
}
//服务端异步代理调用处理器
public static class AsyncProcessor<I extends AsyncIface> extends org.apache.thrift.TBaseAsyncProcessor<I> {
private static final Logger LOGGER = LoggerFactory.getLogger(AsyncProcessor.class.getName());
public AsyncProcessor(I iface) {
super(iface, getProcessMap(new HashMap<String, org.apache.thrift.AsyncProcessFunction<I, ? extends org.apache.thrift.TBase, ?>>()));
}
protected AsyncProcessor(I iface, Map<String, org.apache.thrift.AsyncProcessFunction<I, ? extends org.apache.thrift.TBase, ?>> processMap) {
super(iface, getProcessMap(processMap));
}
private static <I extends AsyncIface> Map<String, org.apache.thrift.AsyncProcessFunction<I, ? extends org.apache.thrift.TBase,?>> getProcessMap(Map<String, org.apache.thrift.AsyncProcessFunction<I, ? extends org.apache.thrift.TBase, ?>> processMap) {
processMap.put("sayHello", new sayHello());
return processMap;
}
public static class sayHello<I extends AsyncIface> extends org.apache.thrift.AsyncProcessFunction<I, sayHello_args, String> {
public sayHello() {
super("sayHello");
}
public sayHello_args getEmptyArgsInstance() {
return new sayHello_args();
}
public AsyncMethodCallback<String> getResultHandler(final AsyncFrameBuffer fb, final int seqid) {
final org.apache.thrift.AsyncProcessFunction fcall = this;
return new AsyncMethodCallback<String>() {
public void onComplete(String o) {
sayHello_result result = new sayHello_result();
result.success = o;
try {
fcall.sendResponse(fb,result, org.apache.thrift.protocol.TMessageType.REPLY,seqid);
return;
} catch (Exception e) {
LOGGER.error("Exception writing to internal frame buffer", e);
}
fb.close();
}
public void onError(Exception e) {
byte msgType = org.apache.thrift.protocol.TMessageType.REPLY;
org.apache.thrift.TBase msg;
{
msgType = org.apache.thrift.protocol.TMessageType.EXCEPTION;
msg = (org.apache.thrift.TBase)new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.INTERNAL_ERROR, e.getMessage());
}
try {
fcall.sendResponse(fb,msg,msgType,seqid);
return;
} catch (Exception ex) {
LOGGER.error("Exception writing to internal frame buffer", ex);
}
fb.close();
}
};
}
protected boolean isOneway() {
return false;
}
public void start(I iface, sayHello_args args, org.apache.thrift.async.AsyncMethodCallback<String> resultHandler) throws TException {
iface.sayHello(args.username,resultHandler);
}
}
}
//参数
public static class sayHello_args implements org.apache.thrift.TBase<sayHello_args, sayHello_args._Fields>, java.io.Serializable, Cloneable, Comparable<sayHello_args> {
private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("sayHello_args");
private static final org.apache.thrift.protocol.TField USERNAME_FIELD_DESC = new org.apache.thrift.protocol.TField("username", org.apache.thrift.protocol.TType.STRING, (short)1);
private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
static {
schemes.put(StandardScheme.class, new sayHello_argsStandardSchemeFactory());
schemes.put(TupleScheme.class, new sayHello_argsTupleSchemeFactory());
}
public String username; // required
/** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
public enum _Fields implements org.apache.thrift.TFieldIdEnum {
USERNAME((short)1, "username");
private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();
static {
for (_Fields field : EnumSet.allOf(_Fields.class)) {
byName.put(field.getFieldName(), field);
}
}
/**
* Find the _Fields constant that matches fieldId, or null if its not found.
*/
public static _Fields findByThriftId(int fieldId) {
switch(fieldId) {
case 1: // USERNAME
return USERNAME;
default:
return null;
}
}
/**
* Find the _Fields constant that matches fieldId, throwing an exception
* if it is not found.
*/
public static _Fields findByThriftIdOrThrow(int fieldId) {
_Fields fields = findByThriftId(fieldId);
if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
return fields;
}
/**
* Find the _Fields constant that matches name, or null if its not found.
*/
public static _Fields findByName(String name) {
return byName.get(name);
}
private final short _thriftId;
private final String _fieldName;
_Fields(short thriftId, String fieldName) {
_thriftId = thriftId;
_fieldName = fieldName;
}
public short getThriftFieldId() {
return _thriftId;
}
public String getFieldName() {
return _fieldName;
}
}
// isset id assignments
public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
static {
Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
tmpMap.put(_Fields.USERNAME, new org.apache.thrift.meta_data.FieldMetaData("username", org.apache.thrift.TFieldRequirementType.DEFAULT,
new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
metaDataMap = Collections.unmodifiableMap(tmpMap);
org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(sayHello_args.class, metaDataMap);
}
public sayHello_args() {
}
public sayHello_args(
String username)
{
this();
this.username = username;
}
/**
* Performs a deep copy on <i>other</i>.
*/
public sayHello_args(sayHello_args other) {
if (other.isSetUsername()) {
this.username = other.username;
}
}
public sayHello_args deepCopy() {
return new sayHello_args(this);
}
@Override
public void clear() {
this.username = null;
}
public String getUsername() {
return this.username;
}
public sayHello_args setUsername(String username) {
this.username = username;
return this;
}
public void unsetUsername() {
this.username = null;
}
/** Returns true if field username is set (has been assigned a value) and false otherwise */
public boolean isSetUsername() {
return this.username != null;
}
public void setUsernameIsSet(boolean value) {
if (!value) {
this.username = null;
}
}
public void setFieldValue(_Fields field, Object value) {
switch (field) {
case USERNAME:
if (value == null) {
unsetUsername();
} else {
setUsername((String)value);
}
break;
}
}
public Object getFieldValue(_Fields field) {
switch (field) {
case USERNAME:
return getUsername();
}
throw new IllegalStateException();
}
/** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
public boolean isSet(_Fields field) {
if (field == null) {
throw new IllegalArgumentException();
}
switch (field) {
case USERNAME:
return isSetUsername();
}
throw new IllegalStateException();
}
@Override
public boolean equals(Object that) {
if (that == null)
return false;
if (that instanceof sayHello_args)
return this.equals((sayHello_args)that);
return false;
}
public boolean equals(sayHello_args that) {
if (that == null)
return false;
boolean this_present_username = true && this.isSetUsername();
boolean that_present_username = true && that.isSetUsername();
if (this_present_username || that_present_username) {
if (!(this_present_username && that_present_username))
return false;
if (!this.username.equals(that.username))
return false;
}
return true;
}
@Override
public int hashCode() {
List<Object> list = new ArrayList<Object>();
boolean present_username = true && (isSetUsername());
list.add(present_username);
if (present_username)
list.add(username);
return list.hashCode();
}
@Override
public int compareTo(sayHello_args other) {
if (!getClass().equals(other.getClass())) {
return getClass().getName().compareTo(other.getClass().getName());
}
int lastComparison = 0;
lastComparison = Boolean.valueOf(isSetUsername()).compareTo(other.isSetUsername());
if (lastComparison != 0) {
return lastComparison;
}
if (isSetUsername()) {
lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.username, other.username);
if (lastComparison != 0) {
return lastComparison;
}
}
return 0;
}
public _Fields fieldForId(int fieldId) {
return _Fields.findByThriftId(fieldId);
}
public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
}
public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder("sayHello_args(");
sb.append("username:");
if (this.username == null) {
sb.append("null");
} else {
sb.append(this.username);
}
sb.append(")");
return sb.toString();
}
public void validate() throws org.apache.thrift.TException {
// check for required fields
// check for sub-struct validity
}
private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
try {
write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
} catch (org.apache.thrift.TException te) {
throw new java.io.IOException(te);
}
}
private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
try {
read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
} catch (org.apache.thrift.TException te) {
throw new java.io.IOException(te);
}
}
private static class sayHello_argsStandardSchemeFactory implements SchemeFactory {
public sayHello_argsStandardScheme getScheme() {
return new sayHello_argsStandardScheme();
}
}
private static class sayHello_argsStandardScheme extends StandardScheme<sayHello_args> {
public void read(org.apache.thrift.protocol.TProtocol iprot, sayHello_args struct) throws org.apache.thrift.TException {
org.apache.thrift.protocol.TField schemeField;
iprot.readStructBegin();
while (true)
{
schemeField = iprot.readFieldBegin();
if (schemeField.type == org.apache.thrift.protocol.TType.STOP) {
break;
}
switch (schemeField.id) {
case 1: // USERNAME
if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
struct.username = iprot.readString();
struct.setUsernameIsSet(true);
} else {
org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
}
break;
default:
org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
}
iprot.readFieldEnd();
}
iprot.readStructEnd();
// check for required fields of primitive type, which can't be checked in the validate method
struct.validate();
}
public void write(org.apache.thrift.protocol.TProtocol oprot, sayHello_args struct) throws org.apache.thrift.TException {
struct.validate();
oprot.writeStructBegin(STRUCT_DESC);
if (struct.username != null) {
oprot.writeFieldBegin(USERNAME_FIELD_DESC);
oprot.writeString(struct.username);
oprot.writeFieldEnd();
}
oprot.writeFieldStop();
oprot.writeStructEnd();
}
}
private static class sayHello_argsTupleSchemeFactory implements SchemeFactory {
public sayHello_argsTupleScheme getScheme() {
return new sayHello_argsTupleScheme();
}
}
private static class sayHello_argsTupleScheme extends TupleScheme<sayHello_args> {
@Override
public void write(org.apache.thrift.protocol.TProtocol prot, sayHello_args struct) throws org.apache.thrift.TException {
TTupleProtocol oprot = (TTupleProtocol) prot;
BitSet optionals = new BitSet();
if (struct.isSetUsername()) {
optionals.set(0);
}
oprot.writeBitSet(optionals, 1);
if (struct.isSetUsername()) {
oprot.writeString(struct.username);
}
}
@Override
public void read(org.apache.thrift.protocol.TProtocol prot, sayHello_args struct) throws org.apache.thrift.TException {
TTupleProtocol iprot = (TTupleProtocol) prot;
BitSet incoming = iprot.readBitSet(1);
if (incoming.get(0)) {
struct.username = iprot.readString();
struct.setUsernameIsSet(true);
}
}
}
}
//返回值
public static class sayHello_result implements org.apache.thrift.TBase<sayHello_result, sayHello_result._Fields>, java.io.Serializable, Cloneable, Comparable<sayHello_result> {
private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("sayHello_result");
private static final org.apache.thrift.protocol.TField SUCCESS_FIELD_DESC = new org.apache.thrift.protocol.TField("success", org.apache.thrift.protocol.TType.STRING, (short)0);
private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
static {
schemes.put(StandardScheme.class, new sayHello_resultStandardSchemeFactory());
schemes.put(TupleScheme.class, new sayHello_resultTupleSchemeFactory());
}
public String success; // required
/** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
public enum _Fields implements org.apache.thrift.TFieldIdEnum {
SUCCESS((short)0, "success");
private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();
static {
for (_Fields field : EnumSet.allOf(_Fields.class)) {
byName.put(field.getFieldName(), field);
}
}
/**
* Find the _Fields constant that matches fieldId, or null if its not found.
*/
public static _Fields findByThriftId(int fieldId) {
switch(fieldId) {
case 0: // SUCCESS
return SUCCESS;
default:
return null;
}
}
/**
* Find the _Fields constant that matches fieldId, throwing an exception
* if it is not found.
*/
public static _Fields findByThriftIdOrThrow(int fieldId) {
_Fields fields = findByThriftId(fieldId);
if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
return fields;
}
/**
* Find the _Fields constant that matches name, or null if its not found.
*/
public static _Fields findByName(String name) {
return byName.get(name);
}
private final short _thriftId;
private final String _fieldName;
_Fields(short thriftId, String fieldName) {
_thriftId = thriftId;
_fieldName = fieldName;
}
public short getThriftFieldId() {
return _thriftId;
}
public String getFieldName() {
return _fieldName;
}
}
// isset id assignments
public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
static {
Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
tmpMap.put(_Fields.SUCCESS, new org.apache.thrift.meta_data.FieldMetaData("success", org.apache.thrift.TFieldRequirementType.DEFAULT,
new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
metaDataMap = Collections.unmodifiableMap(tmpMap);
org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(sayHello_result.class, metaDataMap);
}
public sayHello_result() {
}
public sayHello_result(
String success)
{
this();
this.success = success;
}
/**
* Performs a deep copy on <i>other</i>.
*/
public sayHello_result(sayHello_result other) {
if (other.isSetSuccess()) {
this.success = other.success;
}
}
public sayHello_result deepCopy() {
return new sayHello_result(this);
}
@Override
public void clear() {
this.success = null;
}
public String getSuccess() {
return this.success;
}
public sayHello_result setSuccess(String success) {
this.success = success;
return this;
}
public void unsetSuccess() {
this.success = null;
}
/** Returns true if field success is set (has been assigned a value) and false otherwise */
public boolean isSetSuccess() {
return this.success != null;
}
public void setSuccessIsSet(boolean value) {
if (!value) {
this.success = null;
}
}
public void setFieldValue(_Fields field, Object value) {
switch (field) {
case SUCCESS:
if (value == null) {
unsetSuccess();
} else {
setSuccess((String)value);
}
break;
}
}
public Object getFieldValue(_Fields field) {
switch (field) {
case SUCCESS:
return getSuccess();
}
throw new IllegalStateException();
}
/** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
public boolean isSet(_Fields field) {
if (field == null) {
throw new IllegalArgumentException();
}
switch (field) {
case SUCCESS:
return isSetSuccess();
}
throw new IllegalStateException();
}
@Override
public boolean equals(Object that) {
if (that == null)
return false;
if (that instanceof sayHello_result)
return this.equals((sayHello_result)that);
return false;
}
public boolean equals(sayHello_result that) {
if (that == null)
return false;
boolean this_present_success = true && this.isSetSuccess();
boolean that_present_success = true && that.isSetSuccess();
if (this_present_success || that_present_success) {
if (!(this_present_success && that_present_success))
return false;
if (!this.success.equals(that.success))
return false;
}
return true;
}
@Override
public int hashCode() {
List<Object> list = new ArrayList<Object>();
boolean present_success = true && (isSetSuccess());
list.add(present_success);
if (present_success)
list.add(success);
return list.hashCode();
}
@Override
public int compareTo(sayHello_result other) {
if (!getClass().equals(other.getClass())) {
return getClass().getName().compareTo(other.getClass().getName());
}
int lastComparison = 0;
lastComparison = Boolean.valueOf(isSetSuccess()).compareTo(other.isSetSuccess());
if (lastComparison != 0) {
return lastComparison;
}
if (isSetSuccess()) {
lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.success, other.success);
if (lastComparison != 0) {
return lastComparison;
}
}
return 0;
}
public _Fields fieldForId(int fieldId) {
return _Fields.findByThriftId(fieldId);
}
public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
}
public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder("sayHello_result(");
sb.append("success:");
if (this.success == null) {
sb.append("null");
} else {
sb.append(this.success);
}
sb.append(")");
return sb.toString();
}
public void validate() throws org.apache.thrift.TException {
// check for required fields
// check for sub-struct validity
}
private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
try {
write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
} catch (org.apache.thrift.TException te) {
throw new java.io.IOException(te);
}
}
private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
try {
read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
} catch (org.apache.thrift.TException te) {
throw new java.io.IOException(te);
}
}
private static class sayHello_resultStandardSchemeFactory implements SchemeFactory {
public sayHello_resultStandardScheme getScheme() {
return new sayHello_resultStandardScheme();
}
}
private static class sayHello_resultStandardScheme extends StandardScheme<sayHello_result> {
public void read(org.apache.thrift.protocol.TProtocol iprot, sayHello_result struct) throws org.apache.thrift.TException {
org.apache.thrift.protocol.TField schemeField;
iprot.readStructBegin();
while (true)
{
schemeField = iprot.readFieldBegin();
if (schemeField.type == org.apache.thrift.protocol.TType.STOP) {
break;
}
switch (schemeField.id) {
case 0: // SUCCESS
if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
struct.success = iprot.readString();
struct.setSuccessIsSet(true);
} else {
org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
}
break;
default:
org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
}
iprot.readFieldEnd();
}
iprot.readStructEnd();
// check for required fields of primitive type, which can't be checked in the validate method
struct.validate();
}
public void write(org.apache.thrift.protocol.TProtocol oprot, sayHello_result struct) throws org.apache.thrift.TException {
struct.validate();
oprot.writeStructBegin(STRUCT_DESC);
if (struct.success != null) {
oprot.writeFieldBegin(SUCCESS_FIELD_DESC);
oprot.writeString(struct.success);
oprot.writeFieldEnd();
}
oprot.writeFieldStop();
oprot.writeStructEnd();
}
}
private static class sayHello_resultTupleSchemeFactory implements SchemeFactory {
public sayHello_resultTupleScheme getScheme() {
return new sayHello_resultTupleScheme();
}
}
private static class sayHello_resultTupleScheme extends TupleScheme<sayHello_result> {
@Override
public void write(org.apache.thrift.protocol.TProtocol prot, sayHello_result struct) throws org.apache.thrift.TException {
TTupleProtocol oprot = (TTupleProtocol) prot;
BitSet optionals = new BitSet();
if (struct.isSetSuccess()) {
optionals.set(0);
}
oprot.writeBitSet(optionals, 1);
if (struct.isSetSuccess()) {
oprot.writeString(struct.success);
}
}
@Override
public void read(org.apache.thrift.protocol.TProtocol prot, sayHello_result struct) throws org.apache.thrift.TException {
TTupleProtocol iprot = (TTupleProtocol) prot;
BitSet incoming = iprot.readBitSet(1);
if (incoming.get(0)) {
struct.success = iprot.readString();
struct.setSuccessIsSet(true);
}
}
}
}
}
将生成的接口
HelloWorld.java
复制到java工程下.
<dependency>
<groupId>org.apache.thrift</groupId>
<artifactId>libthrift</artifactId>
<version>0.9.2</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.5.8</version>
</dependency>
3.接口实现类
package cn.slimsmart.thrift.demo.helloworld;
import org.apache.thrift.TException;
/**
* HelloWord 接口实现类
*
*/
public class HelloWorldImpl implements HelloWorld.Iface{
@Override
public String sayHello(String username) throws TException {
return "hello world, "+username;
}
}
4.服务器端
package cn.slimsmart.thrift.demo.helloworld;
import org.apache.thrift.TException;
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;
/**
* 注册服务端 阻塞式、单线程
* 简单的单线程服务模型 TSimpleServer
*/
public class HelloTSimpleServer {
// 注册端口
public static final int SERVER_PORT = 8080;
public static void main(String[] args) throws TException {
//设置处理器
TProcessor tprocessor = new HelloWorld.Processor<HelloWorld.Iface>(new HelloWorldImpl());
// 简单的单线程服务模型,阻塞IO
TServerSocket serverTransport = new TServerSocket(SERVER_PORT);
TServer.Args tArgs = new TServer.Args(serverTransport);
tArgs.processor(tprocessor);
使用二进制协议
tArgs.protocolFactory(new TBinaryProtocol.Factory());
//创建服务器
TServer server = new TSimpleServer(tArgs);
System.out.println("HelloServer start....");
server.serve(); // 启动服务
}
}
5.客户端
package cn.slimsmart.thrift.demo.helloworld;
import org.apache.thrift.TException;
import org.apache.thrift.protocol.TBinaryProtocol;
import org.apache.thrift.protocol.TProtocol;
import org.apache.thrift.transport.TSocket;
import org.apache.thrift.transport.TTransport;
/**
* 客户端调用HelloTSimpleServer,HelloTThreadPoolServer
* 阻塞
*/
public class HelloClient {
public static final String SERVER_IP = "127.0.0.1";
public static final int SERVER_PORT = 8080;
public static final int TIMEOUT = 30000;
public static void main(String[] args) throws TException {
// 设置传输通道
TTransport transport = new TSocket(SERVER_IP, SERVER_PORT, TIMEOUT);
// 协议要和服务端一致
//使用二进制协议
TProtocol protocol = new TBinaryProtocol(transport);
//创建Client
HelloWorld.Client client = new HelloWorld.Client(protocol);
transport.open();
String result = client.sayHello("jack");
System.out.println("result : " + result);
//关闭资源
transport.close();
}
}<strong>
</strong>
先运行服务端,再运行客户端,看一下运行结果吧。