Apache Thrift 是FaceBook实现的一种跨平台的远程服务调用(RPC)的框架。它采用接口描述语言(IDL)定义并创建服务,传输数据采用二进制格式,相对于XML和Json等常用数据传输方式体积更小。

首先一个完整的RPC模块主要分三部分:

1.服务层(service):RPC接口的定义与实现

2.协议层(protocol):RPC报文格式和数据编码格式

3.传输层(transport):实现底层的通信(如socket)以及系统相关的功能(如事件循环、多线程)

如上图所示,图中黄色部分是用户实现的业务逻辑,褐色部分是根据Thrift定义的服务接口描述文件生成的客户端和服务端代码框架,红色部分是根据Thrift文件生成代码实现数据的读写操作。红色部分以下是Thrift的传输体系、协议以及底层的I/O通信。

一个thrift简单实例过程:

1.写Thrift定义文件(.thrift)

 namespace java com.eviac.blog.samples.thrift.server  // defines the namespace   

 typedef i32 int  //typedefs to get convenient names for your types  

 service AdditionService {  // defines the service to add two numbers
int add(1:int n1, 2:int n2), //defines a method
}

2.编译Thrift定义文件

thrift --gen <language> <Thrift filename>

对于java语言来说就是:

thrift --gen java add.thrift

执行完之后,在gen-java目录下你会发现构建RPC服务器和客户端有用的源代码,在本例中将生成一个AddtionService.java的文件。

现将生成的代码贴上:

 /**
* Autogenerated by Thrift Compiler (0.8.0-xsb)
*
* DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
* @generated
*/ 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.protocol.TTupleProtocol;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.util.HashMap;
import java.util.EnumMap;
import java.util.Set;
import java.util.HashSet;
import java.util.EnumSet;
import java.util.Collections;
import java.util.BitSet;
import java.nio.ByteBuffer;
import java.util.Arrays;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory; public class AdditionService { public interface Iface { public int add(int n1, int n2) throws org.apache.thrift.TException; } public interface AsyncIface { public void add(int n1, int n2, org.apache.thrift.async.AsyncMethodCallback<AsyncClient.add_call> 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 int add(int n1, int n2) throws org.apache.thrift.TException
{
send_add(n1, n2);
return recv_add();
} public void send_add(int n1, int n2) throws org.apache.thrift.TException
{
add_args args = new add_args();
args.setN1(n1);
args.setN2(n2);
sendBase("add", args);
} public int recv_add() throws org.apache.thrift.TException
{
add_result result = new add_result();
receiveBase(result, "add");
if (result.isSetSuccess()) {
return result.success;
}
throw new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.MISSING_RESULT, "add 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 add(int n1, int n2, org.apache.thrift.async.AsyncMethodCallback<add_call> resultHandler) throws org.apache.thrift.TException {
checkReady();
add_call method_call = new add_call(n1, n2, resultHandler, this, ___protocolFactory, ___transport);
this.___currentMethod = method_call;
___manager.call(method_call);
} public static class add_call extends org.apache.thrift.async.TAsyncMethodCall {
private int n1;
private int n2;
public add_call(int n1, int n2, org.apache.thrift.async.AsyncMethodCallback<add_call> 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.n1 = n1;
this.n2 = n2;
} public void write_args(org.apache.thrift.protocol.TProtocol prot) throws org.apache.thrift.TException {
prot.writeMessageBegin(new org.apache.thrift.protocol.TMessage("add", org.apache.thrift.protocol.TMessageType.CALL, 0));
add_args args = new add_args();
args.setN1(n1);
args.setN2(n2);
args.write(prot);
prot.writeMessageEnd();
} public int 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_add();
}
} } public static class Processor<I extends Iface> extends org.apache.thrift.TBaseProcessor<I> implements org.apache.thrift.TProcessor {
private static final Logger LOGGER = LoggerFactory.getLogger(Processor.class.getName());
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("add", new add());
return processMap;
} private static class add<I extends Iface> extends org.apache.thrift.ProcessFunction<I, add_args> {
public add() {
super("add");
} protected add_args getEmptyArgsInstance() {
return new add_args();
} protected boolean isOneway() {
return false;
} protected add_result getResult(I iface, add_args args) throws org.apache.thrift.TException {
add_result result = new add_result();
result.success = iface.add(args.n1, args.n2);
result.setSuccessIsSet(true);
return result;
}
} } public static class add_args implements org.apache.thrift.TBase<add_args, add_args._Fields>, java.io.Serializable, Cloneable {
private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("add_args"); private static final org.apache.thrift.protocol.TField N1_FIELD_DESC = new org.apache.thrift.protocol.TField("n1", org.apache.thrift.protocol.TType.I32, (short)1);
private static final org.apache.thrift.protocol.TField N2_FIELD_DESC = new org.apache.thrift.protocol.TField("n2", org.apache.thrift.protocol.TType.I32, (short)2); private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
static {
schemes.put(StandardScheme.class, new add_argsStandardSchemeFactory());
schemes.put(TupleScheme.class, new add_argsTupleSchemeFactory());
} public int n1; // required
public int n2; // 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 {
N1((short)1, "n1"),
N2((short)2, "n2"); 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: // N1
return N1;
case 2: // N2
return N2;
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
private static final int __N1_ISSET_ID = 0;
private static final int __N2_ISSET_ID = 1;
private BitSet __isset_bit_vector = new BitSet(2);
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.N1, new org.apache.thrift.meta_data.FieldMetaData("n1", org.apache.thrift.TFieldRequirementType.DEFAULT,
new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.I32 , "int")));
tmpMap.put(_Fields.N2, new org.apache.thrift.meta_data.FieldMetaData("n2", org.apache.thrift.TFieldRequirementType.DEFAULT,
new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.I32 , "int")));
metaDataMap = Collections.unmodifiableMap(tmpMap);
org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(add_args.class, metaDataMap);
} public add_args() {
} public add_args(
int n1,
int n2)
{
this();
this.n1 = n1;
setN1IsSet(true);
this.n2 = n2;
setN2IsSet(true);
} /**
* Performs a deep copy on <i>other</i>.
*/
public add_args(add_args other) {
__isset_bit_vector.clear();
__isset_bit_vector.or(other.__isset_bit_vector);
this.n1 = other.n1;
this.n2 = other.n2;
} public add_args deepCopy() {
return new add_args(this);
} @Override
public void clear() {
setN1IsSet(false);
this.n1 = 0;
setN2IsSet(false);
this.n2 = 0;
} public int getN1() {
return this.n1;
} public add_args setN1(int n1) {
this.n1 = n1;
setN1IsSet(true);
return this;
} public void unsetN1() {
__isset_bit_vector.clear(__N1_ISSET_ID);
} /** Returns true if field n1 is set (has been assigned a value) and false otherwise */
public boolean isSetN1() {
return __isset_bit_vector.get(__N1_ISSET_ID);
} public void setN1IsSet(boolean value) {
__isset_bit_vector.set(__N1_ISSET_ID, value);
} public int getN2() {
return this.n2;
} public add_args setN2(int n2) {
this.n2 = n2;
setN2IsSet(true);
return this;
} public void unsetN2() {
__isset_bit_vector.clear(__N2_ISSET_ID);
} /** Returns true if field n2 is set (has been assigned a value) and false otherwise */
public boolean isSetN2() {
return __isset_bit_vector.get(__N2_ISSET_ID);
} public void setN2IsSet(boolean value) {
__isset_bit_vector.set(__N2_ISSET_ID, value);
} public void setFieldValue(_Fields field, Object value) {
switch (field) {
case N1:
if (value == null) {
unsetN1();
} else {
setN1((Integer)value);
}
break; case N2:
if (value == null) {
unsetN2();
} else {
setN2((Integer)value);
}
break; }
} public Object getFieldValue(_Fields field) {
switch (field) {
case N1:
return Integer.valueOf(getN1()); case N2:
return Integer.valueOf(getN2()); }
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 N1:
return isSetN1();
case N2:
return isSetN2();
}
throw new IllegalStateException();
} @Override
public boolean equals(Object that) {
if (that == null)
return false;
if (that instanceof add_args)
return this.equals((add_args)that);
return false;
} public boolean equals(add_args that) {
if (that == null)
return false; boolean this_present_n1 = true;
boolean that_present_n1 = true;
if (this_present_n1 || that_present_n1) {
if (!(this_present_n1 && that_present_n1))
return false;
if (this.n1 != that.n1)
return false;
} boolean this_present_n2 = true;
boolean that_present_n2 = true;
if (this_present_n2 || that_present_n2) {
if (!(this_present_n2 && that_present_n2))
return false;
if (this.n2 != that.n2)
return false;
} return true;
} @Override
public int hashCode() {
return 0;
} public int compareTo(add_args other) {
if (!getClass().equals(other.getClass())) {
return getClass().getName().compareTo(other.getClass().getName());
} int lastComparison = 0;
add_args typedOther = (add_args)other; lastComparison = Boolean.valueOf(isSetN1()).compareTo(typedOther.isSetN1());
if (lastComparison != 0) {
return lastComparison;
}
if (isSetN1()) {
lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.n1, typedOther.n1);
if (lastComparison != 0) {
return lastComparison;
}
}
lastComparison = Boolean.valueOf(isSetN2()).compareTo(typedOther.isSetN2());
if (lastComparison != 0) {
return lastComparison;
}
if (isSetN2()) {
lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.n2, typedOther.n2);
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("add_args(");
boolean first = true; sb.append("n1:");
sb.append(this.n1);
first = false;
if (!first) sb.append(", ");
sb.append("n2:");
sb.append(this.n2);
first = false;
sb.append(")");
return sb.toString();
} public void validate() throws org.apache.thrift.TException {
// check for required fields
} 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 {
// it doesn't seem like you should have to do this, but java serialization is wacky, and doesn't call the default constructor.
__isset_bit_vector = new BitSet(1);
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 add_argsStandardSchemeFactory implements SchemeFactory {
public add_argsStandardScheme getScheme() {
return new add_argsStandardScheme();
}
} private static class add_argsStandardScheme extends StandardScheme<add_args> { public void read(org.apache.thrift.protocol.TProtocol iprot, add_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: // N1
if (schemeField.type == org.apache.thrift.protocol.TType.I32) {
struct.n1 = iprot.readI32();
struct.setN1IsSet(true);
} else {
org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
}
break;
case 2: // N2
if (schemeField.type == org.apache.thrift.protocol.TType.I32) {
struct.n2 = iprot.readI32();
struct.setN2IsSet(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, add_args struct) throws org.apache.thrift.TException {
struct.validate(); oprot.writeStructBegin(STRUCT_DESC);
oprot.writeFieldBegin(N1_FIELD_DESC);
oprot.writeI32(struct.n1);
oprot.writeFieldEnd();
oprot.writeFieldBegin(N2_FIELD_DESC);
oprot.writeI32(struct.n2);
oprot.writeFieldEnd();
oprot.writeFieldStop();
oprot.writeStructEnd();
} } private static class add_argsTupleSchemeFactory implements SchemeFactory {
public add_argsTupleScheme getScheme() {
return new add_argsTupleScheme();
}
} private static class add_argsTupleScheme extends TupleScheme<add_args> { @Override
public void write(org.apache.thrift.protocol.TProtocol prot, add_args struct) throws org.apache.thrift.TException {
TTupleProtocol oprot = (TTupleProtocol) prot;
BitSet optionals = new BitSet();
if (struct.isSetN1()) {
optionals.set(0);
}
if (struct.isSetN2()) {
optionals.set(1);
}
oprot.writeBitSet(optionals, 2);
if (struct.isSetN1()) {
oprot.writeI32(struct.n1);
}
if (struct.isSetN2()) {
oprot.writeI32(struct.n2);
}
} @Override
public void read(org.apache.thrift.protocol.TProtocol prot, add_args struct) throws org.apache.thrift.TException {
TTupleProtocol iprot = (TTupleProtocol) prot;
BitSet incoming = iprot.readBitSet(2);
if (incoming.get(0)) {
struct.n1 = iprot.readI32();
struct.setN1IsSet(true);
}
if (incoming.get(1)) {
struct.n2 = iprot.readI32();
struct.setN2IsSet(true);
}
}
} } public static class add_result implements org.apache.thrift.TBase<add_result, add_result._Fields>, java.io.Serializable, Cloneable {
private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("add_result"); private static final org.apache.thrift.protocol.TField SUCCESS_FIELD_DESC = new org.apache.thrift.protocol.TField("success", org.apache.thrift.protocol.TType.I32, (short)0); private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
static {
schemes.put(StandardScheme.class, new add_resultStandardSchemeFactory());
schemes.put(TupleScheme.class, new add_resultTupleSchemeFactory());
} public int 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
private static final int __SUCCESS_ISSET_ID = 0;
private BitSet __isset_bit_vector = new BitSet(1);
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.I32 , "int")));
metaDataMap = Collections.unmodifiableMap(tmpMap);
org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(add_result.class, metaDataMap);
} public add_result() {
} public add_result(
int success)
{
this();
this.success = success;
setSuccessIsSet(true);
} /**
* Performs a deep copy on <i>other</i>.
*/
public add_result(add_result other) {
__isset_bit_vector.clear();
__isset_bit_vector.or(other.__isset_bit_vector);
this.success = other.success;
} public add_result deepCopy() {
return new add_result(this);
} @Override
public void clear() {
setSuccessIsSet(false);
this.success = 0;
} public int getSuccess() {
return this.success;
} public add_result setSuccess(int success) {
this.success = success;
setSuccessIsSet(true);
return this;
} public void unsetSuccess() {
__isset_bit_vector.clear(__SUCCESS_ISSET_ID);
} /** Returns true if field success is set (has been assigned a value) and false otherwise */
public boolean isSetSuccess() {
return __isset_bit_vector.get(__SUCCESS_ISSET_ID);
} public void setSuccessIsSet(boolean value) {
__isset_bit_vector.set(__SUCCESS_ISSET_ID, value);
} public void setFieldValue(_Fields field, Object value) {
switch (field) {
case SUCCESS:
if (value == null) {
unsetSuccess();
} else {
setSuccess((Integer)value);
}
break; }
} public Object getFieldValue(_Fields field) {
switch (field) {
case SUCCESS:
return Integer.valueOf(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 add_result)
return this.equals((add_result)that);
return false;
} public boolean equals(add_result that) {
if (that == null)
return false; boolean this_present_success = true;
boolean that_present_success = true;
if (this_present_success || that_present_success) {
if (!(this_present_success && that_present_success))
return false;
if (this.success != that.success)
return false;
} return true;
} @Override
public int hashCode() {
return 0;
} public int compareTo(add_result other) {
if (!getClass().equals(other.getClass())) {
return getClass().getName().compareTo(other.getClass().getName());
} int lastComparison = 0;
add_result typedOther = (add_result)other; lastComparison = Boolean.valueOf(isSetSuccess()).compareTo(typedOther.isSetSuccess());
if (lastComparison != 0) {
return lastComparison;
}
if (isSetSuccess()) {
lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.success, typedOther.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("add_result(");
boolean first = true; sb.append("success:");
sb.append(this.success);
first = false;
sb.append(")");
return sb.toString();
} public void validate() throws org.apache.thrift.TException {
// check for required fields
} 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 add_resultStandardSchemeFactory implements SchemeFactory {
public add_resultStandardScheme getScheme() {
return new add_resultStandardScheme();
}
} private static class add_resultStandardScheme extends StandardScheme<add_result> { public void read(org.apache.thrift.protocol.TProtocol iprot, add_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.I32) {
struct.success = iprot.readI32();
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, add_result struct) throws org.apache.thrift.TException {
struct.validate(); oprot.writeStructBegin(STRUCT_DESC);
oprot.writeFieldBegin(SUCCESS_FIELD_DESC);
oprot.writeI32(struct.success);
oprot.writeFieldEnd();
oprot.writeFieldStop();
oprot.writeStructEnd();
} } private static class add_resultTupleSchemeFactory implements SchemeFactory {
public add_resultTupleScheme getScheme() {
return new add_resultTupleScheme();
}
} private static class add_resultTupleScheme extends TupleScheme<add_result> { @Override
public void write(org.apache.thrift.protocol.TProtocol prot, add_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.writeI32(struct.success);
}
} @Override
public void read(org.apache.thrift.protocol.TProtocol prot, add_result struct) throws org.apache.thrift.TException {
TTupleProtocol iprot = (TTupleProtocol) prot;
BitSet incoming = iprot.readBitSet(1);
if (incoming.get(0)) {
struct.success = iprot.readI32();
struct.setSuccessIsSet(true);
}
}
} } }

3.写一个service handler(也可以叫serviceImpl)

Service handler 类必须实现 AdditionService.Iface接口。AdditionServiceHandler.java代码如下:

 import org.apache.thrift.TException;

 public class AdditionServiceHandler implements AdditionService.Iface{

     @Override
public int add(int n1, int n2) throws TException {
// TODO Auto-generated method stub
return n1 + n2;
} }

4.写一个简单的服务器

下面的示例代码是一个简单的Thrift服务器。可以看到下面的代码中有一段是注释了的,可以去掉注释来启用多线程服务器。
示例服务器(MyServer.java)

 import org.apache.thrift.transport.TServerSocket;
import org.apache.thrift.transport.TServerTransport;
import org.apache.thrift.server.TServer;
import org.apache.thrift.server.TServer.Args;
import org.apache.thrift.server.TSimpleServer; public class MyServer { public static void StartsimpleServer(AdditionService.Processor<AdditionServiceHandler> processor) {
try {
TServerTransport serverTransport = new TServerSocket(9090);
TServer server = new TSimpleServer(
new Args(serverTransport).processor(processor)); // Use this for a multithreaded server
// TServer server = new TThreadPoolServer(new
// TThreadPoolServer.Args(serverTransport).processor(processor)); System.out.println("Starting the simple server...");
server.serve();
} catch (Exception e) {
e.printStackTrace();
}
} public static void main(String[] args) {
StartsimpleServer(new AdditionService.Processor<AdditionServiceHandler>(new AdditionServiceHandler()));
} }

5.写一个简单的客户端

下面的例子是一个使用Java写的客户端短使用AdditionService的服务。

 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;
import org.apache.thrift.transport.TTransportException; public class AdditionClient { public static void main(String[] args) { try {
TTransport transport; transport = new TSocket("localhost", 9090);
transport.open(); TProtocol protocol = new TBinaryProtocol(transport);
AdditionService.Client client = new AdditionService.Client(protocol); System.out.println(client.add(100, 200)); transport.close();
} catch (TTransportException e) {
e.printStackTrace();
} catch (TException x) {
x.printStackTrace();
}
} }

运行服务端代码(MyServer.java)将会看到下面的输出。

Starting the simple server...

然后运行客户端代码(AdditionClient.java),将会看到如下输出。

300

Thrift主要由五个部分组成:

系统类型以及IDL编译器:负责由用户给定的IDL文件生成相应语言的接口代码。

Tprotocol:实现RPC的协议层,可以选择多种不同的对象串行化方式,如JSON,Binary.

Transport:实现RPC的传输层,同样可以选择不同的传输层实现,如socket,非阻塞的socket等。

Tprocessor:作为协议层和用户提供的服务实现之间的纽带,负责调用服务实现的接口。

Tserver:聚合TProtocol,TTransport和TProcessor几个对象。

上述的这5个部件都是在 Thrift 的源代码中通过为不同语言提供库来实现的,这些库的代码在 Thrift 源码目录的 lib 目录下面,在使用 Thrift 之前需要先熟悉与自己的语言对应的库提供的接口。

数据类型

Thrift 脚本可定义的数据类型包括以下几种类型:

  • 基本类型:
  • bool:布尔值,true 或 false,对应 Java 的 boolean
  • byte:8 位有符号整数,对应 Java 的 byte
  • i16:16 位有符号整数,对应 Java 的 short
  • i32:32 位有符号整数,对应 Java 的 int
  • i64:64 位有符号整数,对应 Java 的 long
  • double:64 位浮点数,对应 Java 的 double
  • string:未知编码文本或二进制字符串,对应 Java 的 String
  • 结构体类型:

    • struct:定义公共的对象,类似于 C 语言中的结构体定义,在 Java 中是一个 JavaBean
  • 容器类型:
    • list:对应 Java 的 ArrayList
    • set:对应 Java 的 HashSet
    • map:对应 Java 的 HashMap
  • 异常类型:
    • exception:对应 Java 的 Exception
  • 服务类型:
    • service:对应服务的类

协议

Thrift 可以让用户选择客户端与服务端之间传输通信协议的类别,在传输协议上总体划分为文本 (text) 和二进制 (binary) 传输协议,为节约带宽,提高传输效率,一般情况下使用二进制类型的传输协议为多数,有时还会使用基于文本类型的协议,这需要根据项目 / 产品中的实际需求。常用协议有以下几种:

TBinaryProtocol —— 二进制编码格式进行数据传输

TCompactProtocol —— 高效率的、密集的二进制编码格式进行数据传输

TJSONProtocol —— 使用 JSON 的数据编码协议进行数据传输

TSimpleJSONProtocol —— 只提供 JSON 只写的协议,适用于通过脚本语言解析

传输层

常用的传输层有以下几种:

1.TSocket —— 使用阻塞式 I/O 进行传输,是最常见的模式

2.TFramedTransport —— 使用非阻塞方式,按块的大小进行传输,类似于 Java 中的 NIO

若使用 TFramedTransport 传输层,其服务器必须修改为非阻塞的服务类型,TNonblockingServerTransport 类是构建非阻塞 socket 的抽象类,TNonblockingServerSocket 类继承 TNonblockingServerTransport

3.TNonblockingTransport —— 使用非阻塞方式,用于构建异步客户端

服务端类型

常见的服务端类型有以下几种:

1.TSimpleServer —— 单线程服务器端使用标准的阻塞式 I/O

2.TThreadPoolServer —— 多线程服务器端使用标准的阻塞式 I/O

3.TNonblockingServer —— 多线程服务器端使用非阻塞式 I/O

本文参考以及引用:http://www.ibm.com/developerworks/cn/java/j-lo-apachethrift/

http://my.oschina.net/jack230230/blog/66041

thrift概述的更多相关文章

  1. 【转载】Thrift概述

    来自 <https://www.ibm.com/developerworks/cn/java/j-lo-apachethrift/#ibm-pcon> 一个简单的 Thrift 实例 首先 ...

  2. 【通信框架】Apache的开源通信框架thrift概述

    在阅读的过程中有不论什么问题.欢迎一起交流 邮箱:1494713801@qq.com    QQ:1494713801 一.作用 Thrift("Scalable Cross-Languag ...

  3. Thrift 跨服务开发框架

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

  4. [ToDo]Thrift学习

    这里有较详细的Java项目配置过程: http://bglmmz.iteye.com/blog/2058785 下面有Java项目的示例介绍: http://www.tuicool.com/artic ...

  5. .Net 大型分布式基础服务架构横向演变概述

    一. 业务背景 构建具备高可用,高扩展性,高性能,能承载高并发,大流量的分布式电子商务平台,支持用户,订单,采购,物流,配送,财务等多个项目的协作,便于后续运营报表,分析,便于运维及监控. 二. 基础 ...

  6. Thrift入门及Java实例演示<转载备用>

    Thrift入门及Java实例演示 作者: Michael 日期: 年 月 日 •概述 •下载配置 •基本概念 .数据类型 .服务端编码基本步骤 .客户端编码基本步骤 .数据传输协议 •实例演示(ja ...

  7. Hadoop学习笔记【Hadoop家族成员概述】

    Hadoop家族成员概述 一.Hadoop简介 1.1 什么是Hadoop? Hadoop是一个分布式系统基础架构,由Apache基金会所开发,目前Yahoo!是其最重要的贡献者. Hadoop实现了 ...

  8. Thrift入门及Java实例演示

    目录: 概述 下载配置 基本概念 数据类型 服务端编码基本步骤 客户端编码基本步骤 数据传输协议 实例演示(java) thrift生成代码 实现接口Iface TSimpleServer服务模型 T ...

  9. Apache Thrift学习之一(入门及Java实例演示)

    目录: 概述 下载配置 基本概念 数据类型 服务端编码基本步骤 客户端编码基本步骤 数据传输协议 实例演示(java) thrift生成代码 实现接口Iface TSimpleServer服务模型 T ...

随机推荐

  1. OPENSSL简介

    1. 什么是 SSL? SSL 是一个缩写,代表的是Secure Sockets Layer. 它是支持在Internet 上进行安全通信的标准,并且将数据密码术集成到了协议之中. 数据在离开您的计算 ...

  2. hdu_5894_hannnnah_j’s Biological Test(打表找规律)

    题目链接:hdu_5894_hannnnah_j’s Biological Test 题意: 有n个不同的位置围成一个圈,现在要安排m个人坐,每个人至少的间隔为k,问有多少种安排 题解: 先打表找规律 ...

  3. 关于R语言的一些编程经验

    一个晚上写出一个能用的程序…… 来说说遇见的问题吧 zqw<-read.table(file = "c:/data/zqw.txt") zqw<-data.frame( ...

  4. uint8与double,二维矩阵显示灰度图

    double型0~1对应uint8型0~255,转换用im2double和im2uint8 如果直接用uint8(double型),则为0~1的uint8型数据,图像全黑. 处理数据过程推荐用doub ...

  5. strings

    3.1.1.1 计算列表中的字符串数目 使用Count属性可计算列表中的字符串数目.Count是只读属性,用以指示列表中字符串列表数目.因为字符串列表是以零开始索引,因而Count比列表的最大索引数大 ...

  6. Openjudge-计算概论(A)-球弹跳高度的计算

    描述: 一球从某一高度落下(整数,单位米),每次落地后反跳回原来高度的一半,再落下.编程计算气球在第10次落地时,共经过多少米? 第10次反弹多高?输入输入一个整数h,表示球的初始高度.输出输出包含两 ...

  7. BOOTICE(引导扇区维护工具) V1.3.3 中文免费绿色版

    软件名称: BOOTICE(引导扇区维护工具)软件语言: 简体中文授权方式: 免费软件运行环境: Win7 / Vista / Win2003 / WinXP 软件大小: 357KB图片预览: 软件简 ...

  8. javascript焦点图之缓冲滚动无缝切换

    在用于实现无缝切换四张图,所以设置了6个图片就是 4,0,1,2,3,4,0 <!DOCTYPE html> <html> <head> <meta char ...

  9. Html 嵌入 swf

    1. object + embed       传统的方法 优点:浏览器兼容性好,是 Macromedia 一直以来的官方方法缺点:a.embed 标签是不符合 W3C 的规范的,无法通过验证.当然, ...

  10. java代理的深入浅出(三)-JavaAssist,ASM

    简介 类似字节码操作方法还有ASM.几种动态编程方法相比较,在性能上Javassist高于反射,但低于ASM,因为Javassist增加了一层抽象.在实现成本上Javassist和反射都很低,而ASM ...