thrift概述

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

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

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

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

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

图 1. 架构图

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

一个thrift简单实例过程:

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

1 namespace java com.eviac.blog.samples.thrift.server  // defines the namespace   
2    
3 typedef i32 int  //typedefs to get convenient names for your types  
4    
5 service AdditionService {  // defines the service to add two numbers  
6         int add(1:int n1, 2:int n2), //defines a method  
7 }

2.编译Thrift定义文件

thrift --gen <language> <Thrift filename>

对于java语言来说就是:

thrift --gen java add.thrift

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

现将生成的代码贴上:

  1 /**
  2  * Autogenerated by Thrift Compiler (0.8.0-xsb)
  3  *
  4  * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
  5  *  @generated
  6  */
  7 
  8 
  9 import org.apache.thrift.scheme.IScheme;
 10 import org.apache.thrift.scheme.SchemeFactory;
 11 import org.apache.thrift.scheme.StandardScheme;
 12 
 13 import org.apache.thrift.scheme.TupleScheme;
 14 import org.apache.thrift.protocol.TTupleProtocol;
 15 import java.util.List;
 16 import java.util.ArrayList;
 17 import java.util.Map;
 18 import java.util.HashMap;
 19 import java.util.EnumMap;
 20 import java.util.Set;
 21 import java.util.HashSet;
 22 import java.util.EnumSet;
 23 import java.util.Collections;
 24 import java.util.BitSet;
 25 import java.nio.ByteBuffer;
 26 import java.util.Arrays;
 27 import org.slf4j.Logger;
 28 import org.slf4j.LoggerFactory;
 29 
 30 public class AdditionService {
 31 
 32   public interface Iface {
 33 
 34     public int add(int n1, int n2) throws org.apache.thrift.TException;
 35 
 36   }
 37 
 38   public interface AsyncIface {
 39 
 40     public void add(int n1, int n2, org.apache.thrift.async.AsyncMethodCallback<AsyncClient.add_call> resultHandler) throws org.apache.thrift.TException;
 41 
 42   }
 43 
 44   public static class Client extends org.apache.thrift.TServiceClient implements Iface {
 45     public static class Factory implements org.apache.thrift.TServiceClientFactory<Client> {
 46       public Factory() {}
 47       public Client getClient(org.apache.thrift.protocol.TProtocol prot) {
 48         return new Client(prot);
 49       }
 50       public Client getClient(org.apache.thrift.protocol.TProtocol iprot, org.apache.thrift.protocol.TProtocol oprot) {
 51         return new Client(iprot, oprot);
 52       }
 53     }
 54 
 55     public Client(org.apache.thrift.protocol.TProtocol prot)
 56     {
 57       super(prot, prot);
 58     }
 59 
 60     public Client(org.apache.thrift.protocol.TProtocol iprot, org.apache.thrift.protocol.TProtocol oprot) {
 61       super(iprot, oprot);
 62     }
 63 
 64     public int add(int n1, int n2) throws org.apache.thrift.TException
 65     {
 66       send_add(n1, n2);
 67       return recv_add();
 68     }
 69 
 70     public void send_add(int n1, int n2) throws org.apache.thrift.TException
 71     {
 72       add_args args = new add_args();
 73       args.setN1(n1);
 74       args.setN2(n2);
 75       sendBase("add", args);
 76     }
 77 
 78     public int recv_add() throws org.apache.thrift.TException
 79     {
 80       add_result result = new add_result();
 81       receiveBase(result, "add");
 82       if (result.isSetSuccess()) {
 83         return result.success;
 84       }
 85       throw new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.MISSING_RESULT, "add failed: unknown result");
 86     }
 87 
 88   }
 89   public static class AsyncClient extends org.apache.thrift.async.TAsyncClient implements AsyncIface {
 90     public static class Factory implements org.apache.thrift.async.TAsyncClientFactory<AsyncClient> {
 91       private org.apache.thrift.async.TAsyncClientManager clientManager;
 92       private org.apache.thrift.protocol.TProtocolFactory protocolFactory;
 93       public Factory(org.apache.thrift.async.TAsyncClientManager clientManager, org.apache.thrift.protocol.TProtocolFactory protocolFactory) {
 94         this.clientManager = clientManager;
 95         this.protocolFactory = protocolFactory;
 96       }
 97       public AsyncClient getAsyncClient(org.apache.thrift.transport.TNonblockingTransport transport) {
 98         return new AsyncClient(protocolFactory, clientManager, transport);
 99       }
100     }
101 
102     public AsyncClient(org.apache.thrift.protocol.TProtocolFactory protocolFactory, org.apache.thrift.async.TAsyncClientManager clientManager, org.apache.thrift.transport.TNonblockingTransport transport) {
103       super(protocolFactory, clientManager, transport);
104     }
105 
106     public void add(int n1, int n2, org.apache.thrift.async.AsyncMethodCallback<add_call> resultHandler) throws org.apache.thrift.TException {
107       checkReady();
108       add_call method_call = new add_call(n1, n2, resultHandler, this, ___protocolFactory, ___transport);
109       this.___currentMethod = method_call;
110       ___manager.call(method_call);
111     }
112 
113     public static class add_call extends org.apache.thrift.async.TAsyncMethodCall {
114       private int n1;
115       private int n2;
116       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 {
117         super(client, protocolFactory, transport, resultHandler, false);
118         this.n1 = n1;
119         this.n2 = n2;
120       }
121 
122       public void write_args(org.apache.thrift.protocol.TProtocol prot) throws org.apache.thrift.TException {
123         prot.writeMessageBegin(new org.apache.thrift.protocol.TMessage("add", org.apache.thrift.protocol.TMessageType.CALL, 0));
124         add_args args = new add_args();
125         args.setN1(n1);
126         args.setN2(n2);
127         args.write(prot);
128         prot.writeMessageEnd();
129       }
130 
131       public int getResult() throws org.apache.thrift.TException {
132         if (getState() != org.apache.thrift.async.TAsyncMethodCall.State.RESPONSE_READ) {
133           throw new IllegalStateException("Method call not finished!");
134         }
135         org.apache.thrift.transport.TMemoryInputTransport memoryTransport = new org.apache.thrift.transport.TMemoryInputTransport(getFrameBuffer().array());
136         org.apache.thrift.protocol.TProtocol prot = client.getProtocolFactory().getProtocol(memoryTransport);
137         return (new Client(prot)).recv_add();
138       }
139     }
140 
141   }
142 
143   public static class Processor<I extends Iface> extends org.apache.thrift.TBaseProcessor<I> implements org.apache.thrift.TProcessor {
144     private static final Logger LOGGER = LoggerFactory.getLogger(Processor.class.getName());
145     public Processor(I iface) {
146       super(iface, getProcessMap(new HashMap<String, org.apache.thrift.ProcessFunction<I, ? extends org.apache.thrift.TBase>>()));
147     }
148 
149     protected Processor(I iface, Map<String,  org.apache.thrift.ProcessFunction<I, ? extends  org.apache.thrift.TBase>> processMap) {
150       super(iface, getProcessMap(processMap));
151     }
152 
153     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) {
154       processMap.put("add", new add());
155       return processMap;
156     }
157 
158     private static class add<I extends Iface> extends org.apache.thrift.ProcessFunction<I, add_args> {
159       public add() {
160         super("add");
161       }
162 
163       protected add_args getEmptyArgsInstance() {
164         return new add_args();
165       }
166 
167       protected boolean isOneway() {
168        return false;
169       }
170 
171       protected add_result getResult(I iface, add_args args) throws org.apache.thrift.TException {
172         add_result result = new add_result();
173         result.success = iface.add(args.n1, args.n2);
174         result.setSuccessIsSet(true);
175         return result;
176       }
177     }
178 
179   }
180 
181   public static class add_args implements org.apache.thrift.TBase<add_args, add_args._Fields>, java.io.Serializable, Cloneable   {
182     private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("add_args");
183 
184     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);
185     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);
186 
187     private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
188     static {
189       schemes.put(StandardScheme.class, new add_argsStandardSchemeFactory());
190       schemes.put(TupleScheme.class, new add_argsTupleSchemeFactory());
191     }
192 
193     public int n1; // required
194     public int n2; // required
195 
196     /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
197     public enum _Fields implements org.apache.thrift.TFieldIdEnum {
198       N1((short)1, "n1"),
199       N2((short)2, "n2");
200 
201       private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();
202 
203       static {
204         for (_Fields field : EnumSet.allOf(_Fields.class)) {
205           byName.put(field.getFieldName(), field);
206         }
207       }
208 
209       /**
210        * Find the _Fields constant that matches fieldId, or null if its not found.
211        */
212       public static _Fields findByThriftId(int fieldId) {
213         switch(fieldId) {
214           case 1: // N1
215             return N1;
216           case 2: // N2
217             return N2;
218           default:
219             return null;
220         }
221       }
222 
223       /**
224        * Find the _Fields constant that matches fieldId, throwing an exception
225        * if it is not found.
226        */
227       public static _Fields findByThriftIdOrThrow(int fieldId) {
228         _Fields fields = findByThriftId(fieldId);
229         if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
230         return fields;
231       }
232 
233       /**
234        * Find the _Fields constant that matches name, or null if its not found.
235        */
236       public static _Fields findByName(String name) {
237         return byName.get(name);
238       }
239 
240       private final short _thriftId;
241       private final String _fieldName;
242 
243       _Fields(short thriftId, String fieldName) {
244         _thriftId = thriftId;
245         _fieldName = fieldName;
246       }
247 
248       public short getThriftFieldId() {
249         return _thriftId;
250       }
251 
252       public String getFieldName() {
253         return _fieldName;
254       }
255     }
256 
257     // isset id assignments
258     private static final int __N1_ISSET_ID = 0;
259     private static final int __N2_ISSET_ID = 1;
260     private BitSet __isset_bit_vector = new BitSet(2);
261     public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
262     static {
263       Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
264       tmpMap.put(_Fields.N1, new org.apache.thrift.meta_data.FieldMetaData("n1", org.apache.thrift.TFieldRequirementType.DEFAULT, 
265           new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.I32          , "int")));
266       tmpMap.put(_Fields.N2, new org.apache.thrift.meta_data.FieldMetaData("n2", org.apache.thrift.TFieldRequirementType.DEFAULT, 
267           new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.I32          , "int")));
268       metaDataMap = Collections.unmodifiableMap(tmpMap);
269       org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(add_args.class, metaDataMap);
270     }
271 
272     public add_args() {
273     }
274 
275     public add_args(
276       int n1,
277       int n2)
278     {
279       this();
280       this.n1 = n1;
281       setN1IsSet(true);
282       this.n2 = n2;
283       setN2IsSet(true);
284     }
285 
286     /**
287      * Performs a deep copy on <i>other</i>.
288      */
289     public add_args(add_args other) {
290       __isset_bit_vector.clear();
291       __isset_bit_vector.or(other.__isset_bit_vector);
292       this.n1 = other.n1;
293       this.n2 = other.n2;
294     }
295 
296     public add_args deepCopy() {
297       return new add_args(this);
298     }
299 
300     @Override
301     public void clear() {
302       setN1IsSet(false);
303       this.n1 = 0;
304       setN2IsSet(false);
305       this.n2 = 0;
306     }
307 
308     public int getN1() {
309       return this.n1;
310     }
311 
312     public add_args setN1(int n1) {
313       this.n1 = n1;
314       setN1IsSet(true);
315       return this;
316     }
317 
318     public void unsetN1() {
319       __isset_bit_vector.clear(__N1_ISSET_ID);
320     }
321 
322     /** Returns true if field n1 is set (has been assigned a value) and false otherwise */
323     public boolean isSetN1() {
324       return __isset_bit_vector.get(__N1_ISSET_ID);
325     }
326 
327     public void setN1IsSet(boolean value) {
328       __isset_bit_vector.set(__N1_ISSET_ID, value);
329     }
330 
331     public int getN2() {
332       return this.n2;
333     }
334 
335     public add_args setN2(int n2) {
336       this.n2 = n2;
337       setN2IsSet(true);
338       return this;
339     }
340 
341     public void unsetN2() {
342       __isset_bit_vector.clear(__N2_ISSET_ID);
343     }
344 
345     /** Returns true if field n2 is set (has been assigned a value) and false otherwise */
346     public boolean isSetN2() {
347       return __isset_bit_vector.get(__N2_ISSET_ID);
348     }
349 
350     public void setN2IsSet(boolean value) {
351       __isset_bit_vector.set(__N2_ISSET_ID, value);
352     }
353 
354     public void setFieldValue(_Fields field, Object value) {
355       switch (field) {
356       case N1:
357         if (value == null) {
358           unsetN1();
359         } else {
360           setN1((Integer)value);
361         }
362         break;
363 
364       case N2:
365         if (value == null) {
366           unsetN2();
367         } else {
368           setN2((Integer)value);
369         }
370         break;
371 
372       }
373     }
374 
375     public Object getFieldValue(_Fields field) {
376       switch (field) {
377       case N1:
378         return Integer.valueOf(getN1());
379 
380       case N2:
381         return Integer.valueOf(getN2());
382 
383       }
384       throw new IllegalStateException();
385     }
386 
387     /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
388     public boolean isSet(_Fields field) {
389       if (field == null) {
390         throw new IllegalArgumentException();
391       }
392 
393       switch (field) {
394       case N1:
395         return isSetN1();
396       case N2:
397         return isSetN2();
398       }
399       throw new IllegalStateException();
400     }
401 
402     @Override
403     public boolean equals(Object that) {
404       if (that == null)
405         return false;
406       if (that instanceof add_args)
407         return this.equals((add_args)that);
408       return false;
409     }
410 
411     public boolean equals(add_args that) {
412       if (that == null)
413         return false;
414 
415       boolean this_present_n1 = true;
416       boolean that_present_n1 = true;
417       if (this_present_n1 || that_present_n1) {
418         if (!(this_present_n1 && that_present_n1))
419           return false;
420         if (this.n1 != that.n1)
421           return false;
422       }
423 
424       boolean this_present_n2 = true;
425       boolean that_present_n2 = true;
426       if (this_present_n2 || that_present_n2) {
427         if (!(this_present_n2 && that_present_n2))
428           return false;
429         if (this.n2 != that.n2)
430           return false;
431       }
432 
433       return true;
434     }
435 
436     @Override
437     public int hashCode() {
438       return 0;
439     }
440 
441     public int compareTo(add_args other) {
442       if (!getClass().equals(other.getClass())) {
443         return getClass().getName().compareTo(other.getClass().getName());
444       }
445 
446       int lastComparison = 0;
447       add_args typedOther = (add_args)other;
448 
449       lastComparison = Boolean.valueOf(isSetN1()).compareTo(typedOther.isSetN1());
450       if (lastComparison != 0) {
451         return lastComparison;
452       }
453       if (isSetN1()) {
454         lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.n1, typedOther.n1);
455         if (lastComparison != 0) {
456           return lastComparison;
457         }
458       }
459       lastComparison = Boolean.valueOf(isSetN2()).compareTo(typedOther.isSetN2());
460       if (lastComparison != 0) {
461         return lastComparison;
462       }
463       if (isSetN2()) {
464         lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.n2, typedOther.n2);
465         if (lastComparison != 0) {
466           return lastComparison;
467         }
468       }
469       return 0;
470     }
471 
472     public _Fields fieldForId(int fieldId) {
473       return _Fields.findByThriftId(fieldId);
474     }
475 
476     public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
477       schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
478     }
479 
480     public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
481       schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
482     }
483 
484     @Override
485     public String toString() {
486       StringBuilder sb = new StringBuilder("add_args(");
487       boolean first = true;
488 
489       sb.append("n1:");
490       sb.append(this.n1);
491       first = false;
492       if (!first) sb.append(", ");
493       sb.append("n2:");
494       sb.append(this.n2);
495       first = false;
496       sb.append(")");
497       return sb.toString();
498     }
499 
500     public void validate() throws org.apache.thrift.TException {
501       // check for required fields
502     }
503 
504     private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
505       try {
506         write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
507       } catch (org.apache.thrift.TException te) {
508         throw new java.io.IOException(te);
509       }
510     }
511 
512     private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
513       try {
514         // it doesn't seem like you should have to do this, but java serialization is wacky, and doesn't call the default constructor.
515         __isset_bit_vector = new BitSet(1);
516         read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
517       } catch (org.apache.thrift.TException te) {
518         throw new java.io.IOException(te);
519       }
520     }
521 
522     private static class add_argsStandardSchemeFactory implements SchemeFactory {
523       public add_argsStandardScheme getScheme() {
524         return new add_argsStandardScheme();
525       }
526     }
527 
528     private static class add_argsStandardScheme extends StandardScheme<add_args> {
529 
530       public void read(org.apache.thrift.protocol.TProtocol iprot, add_args struct) throws org.apache.thrift.TException {
531         org.apache.thrift.protocol.TField schemeField;
532         iprot.readStructBegin();
533         while (true)
534         {
535           schemeField = iprot.readFieldBegin();
536           if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
537             break;
538           }
539           switch (schemeField.id) {
540             case 1: // N1
541               if (schemeField.type == org.apache.thrift.protocol.TType.I32) {
542                 struct.n1 = iprot.readI32();
543                 struct.setN1IsSet(true);
544               } else { 
545                 org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
546               }
547               break;
548             case 2: // N2
549               if (schemeField.type == org.apache.thrift.protocol.TType.I32) {
550                 struct.n2 = iprot.readI32();
551                 struct.setN2IsSet(true);
552               } else { 
553                 org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
554               }
555               break;
556             default:
557               org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
558           }
559           iprot.readFieldEnd();
560         }
561         iprot.readStructEnd();
562 
563         // check for required fields of primitive type, which can't be checked in the validate method
564         struct.validate();
565       }
566 
567       public void write(org.apache.thrift.protocol.TProtocol oprot, add_args struct) throws org.apache.thrift.TException {
568         struct.validate();
569 
570         oprot.writeStructBegin(STRUCT_DESC);
571         oprot.writeFieldBegin(N1_FIELD_DESC);
572         oprot.writeI32(struct.n1);
573         oprot.writeFieldEnd();
574         oprot.writeFieldBegin(N2_FIELD_DESC);
575         oprot.writeI32(struct.n2);
576         oprot.writeFieldEnd();
577         oprot.writeFieldStop();
578         oprot.writeStructEnd();
579       }
580 
581     }
582 
583     private static class add_argsTupleSchemeFactory implements SchemeFactory {
584       public add_argsTupleScheme getScheme() {
585         return new add_argsTupleScheme();
586       }
587     }
588 
589     private static class add_argsTupleScheme extends TupleScheme<add_args> {
590 
591       @Override
592       public void write(org.apache.thrift.protocol.TProtocol prot, add_args struct) throws org.apache.thrift.TException {
593         TTupleProtocol oprot = (TTupleProtocol) prot;
594         BitSet optionals = new BitSet();
595         if (struct.isSetN1()) {
596           optionals.set(0);
597         }
598         if (struct.isSetN2()) {
599           optionals.set(1);
600         }
601         oprot.writeBitSet(optionals, 2);
602         if (struct.isSetN1()) {
603           oprot.writeI32(struct.n1);
604         }
605         if (struct.isSetN2()) {
606           oprot.writeI32(struct.n2);
607         }
608       }
609 
610       @Override
611       public void read(org.apache.thrift.protocol.TProtocol prot, add_args struct) throws org.apache.thrift.TException {
612         TTupleProtocol iprot = (TTupleProtocol) prot;
613         BitSet incoming = iprot.readBitSet(2);
614         if (incoming.get(0)) {
615           struct.n1 = iprot.readI32();
616           struct.setN1IsSet(true);
617         }
618         if (incoming.get(1)) {
619           struct.n2 = iprot.readI32();
620           struct.setN2IsSet(true);
621         }
622       }
623     }
624 
625   }
626 
627   public static class add_result implements org.apache.thrift.TBase<add_result, add_result._Fields>, java.io.Serializable, Cloneable   {
628     private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("add_result");
629 
630     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);
631 
632     private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
633     static {
634       schemes.put(StandardScheme.class, new add_resultStandardSchemeFactory());
635       schemes.put(TupleScheme.class, new add_resultTupleSchemeFactory());
636     }
637 
638     public int success; // required
639 
640     /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
641     public enum _Fields implements org.apache.thrift.TFieldIdEnum {
642       SUCCESS((short)0, "success");
643 
644       private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();
645 
646       static {
647         for (_Fields field : EnumSet.allOf(_Fields.class)) {
648           byName.put(field.getFieldName(), field);
649         }
650       }
651 
652       /**
653        * Find the _Fields constant that matches fieldId, or null if its not found.
654        */
655       public static _Fields findByThriftId(int fieldId) {
656         switch(fieldId) {
657           case 0: // SUCCESS
658             return SUCCESS;
659           default:
660             return null;
661         }
662       }
663 
664       /**
665        * Find the _Fields constant that matches fieldId, throwing an exception
666        * if it is not found.
667        */
668       public static _Fields findByThriftIdOrThrow(int fieldId) {
669         _Fields fields = findByThriftId(fieldId);
670         if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
671         return fields;
672       }
673 
674       /**
675        * Find the _Fields constant that matches name, or null if its not found.
676        */
677       public static _Fields findByName(String name) {
678         return byName.get(name);
679       }
680 
681       private final short _thriftId;
682       private final String _fieldName;
683 
684       _Fields(short thriftId, String fieldName) {
685         _thriftId = thriftId;
686         _fieldName = fieldName;
687       }
688 
689       public short getThriftFieldId() {
690         return _thriftId;
691       }
692 
693       public String getFieldName() {
694         return _fieldName;
695       }
696     }
697 
698     // isset id assignments
699     private static final int __SUCCESS_ISSET_ID = 0;
700     private BitSet __isset_bit_vector = new BitSet(1);
701     public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
702     static {
703       Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
704       tmpMap.put(_Fields.SUCCESS, new org.apache.thrift.meta_data.FieldMetaData("success", org.apache.thrift.TFieldRequirementType.DEFAULT, 
705           new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.I32          , "int")));
706       metaDataMap = Collections.unmodifiableMap(tmpMap);
707       org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(add_result.class, metaDataMap);
708     }
709 
710     public add_result() {
711     }
712 
713     public add_result(
714       int success)
715     {
716       this();
717       this.success = success;
718       setSuccessIsSet(true);
719     }
720 
721     /**
722      * Performs a deep copy on <i>other</i>.
723      */
724     public add_result(add_result other) {
725       __isset_bit_vector.clear();
726       __isset_bit_vector.or(other.__isset_bit_vector);
727       this.success = other.success;
728     }
729 
730     public add_result deepCopy() {
731       return new add_result(this);
732     }
733 
734     @Override
735     public void clear() {
736       setSuccessIsSet(false);
737       this.success = 0;
738     }
739 
740     public int getSuccess() {
741       return this.success;
742     }
743 
744     public add_result setSuccess(int success) {
745       this.success = success;
746       setSuccessIsSet(true);
747       return this;
748     }
749 
750     public void unsetSuccess() {
751       __isset_bit_vector.clear(__SUCCESS_ISSET_ID);
752     }
753 
754     /** Returns true if field success is set (has been assigned a value) and false otherwise */
755     public boolean isSetSuccess() {
756       return __isset_bit_vector.get(__SUCCESS_ISSET_ID);
757     }
758 
759     public void setSuccessIsSet(boolean value) {
760       __isset_bit_vector.set(__SUCCESS_ISSET_ID, value);
761     }
762 
763     public void setFieldValue(_Fields field, Object value) {
764       switch (field) {
765       case SUCCESS:
766         if (value == null) {
767           unsetSuccess();
768         } else {
769           setSuccess((Integer)value);
770         }
771         break;
772 
773       }
774     }
775 
776     public Object getFieldValue(_Fields field) {
777       switch (field) {
778       case SUCCESS:
779         return Integer.valueOf(getSuccess());
780 
781       }
782       throw new IllegalStateException();
783     }
784 
785     /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
786     public boolean isSet(_Fields field) {
787       if (field == null) {
788         throw new IllegalArgumentException();
789       }
790 
791       switch (field) {
792       case SUCCESS:
793         return isSetSuccess();
794       }
795       throw new IllegalStateException();
796     }
797 
798     @Override
799     public boolean equals(Object that) {
800       if (that == null)
801         return false;
802       if (that instanceof add_result)
803         return this.equals((add_result)that);
804       return false;
805     }
806 
807     public boolean equals(add_result that) {
808       if (that == null)
809         return false;
810 
811       boolean this_present_success = true;
812       boolean that_present_success = true;
813       if (this_present_success || that_present_success) {
814         if (!(this_present_success && that_present_success))
815           return false;
816         if (this.success != that.success)
817           return false;
818       }
819 
820       return true;
821     }
822 
823     @Override
824     public int hashCode() {
825       return 0;
826     }
827 
828     public int compareTo(add_result other) {
829       if (!getClass().equals(other.getClass())) {
830         return getClass().getName().compareTo(other.getClass().getName());
831       }
832 
833       int lastComparison = 0;
834       add_result typedOther = (add_result)other;
835 
836       lastComparison = Boolean.valueOf(isSetSuccess()).compareTo(typedOther.isSetSuccess());
837       if (lastComparison != 0) {
838         return lastComparison;
839       }
840       if (isSetSuccess()) {
841         lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.success, typedOther.success);
842         if (lastComparison != 0) {
843           return lastComparison;
844         }
845       }
846       return 0;
847     }
848 
849     public _Fields fieldForId(int fieldId) {
850       return _Fields.findByThriftId(fieldId);
851     }
852 
853     public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
854       schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
855     }
856 
857     public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
858       schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
859       }
860 
861     @Override
862     public String toString() {
863       StringBuilder sb = new StringBuilder("add_result(");
864       boolean first = true;
865 
866       sb.append("success:");
867       sb.append(this.success);
868       first = false;
869       sb.append(")");
870       return sb.toString();
871     }
872 
873     public void validate() throws org.apache.thrift.TException {
874       // check for required fields
875     }
876 
877     private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
878       try {
879         write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
880       } catch (org.apache.thrift.TException te) {
881         throw new java.io.IOException(te);
882       }
883     }
884 
885     private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
886       try {
887         read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
888       } catch (org.apache.thrift.TException te) {
889         throw new java.io.IOException(te);
890       }
891     }
892 
893     private static class add_resultStandardSchemeFactory implements SchemeFactory {
894       public add_resultStandardScheme getScheme() {
895         return new add_resultStandardScheme();
896       }
897     }
898 
899     private static class add_resultStandardScheme extends StandardScheme<add_result> {
900 
901       public void read(org.apache.thrift.protocol.TProtocol iprot, add_result struct) throws org.apache.thrift.TException {
902         org.apache.thrift.protocol.TField schemeField;
903         iprot.readStructBegin();
904         while (true)
905         {
906           schemeField = iprot.readFieldBegin();
907           if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
908             break;
909           }
910           switch (schemeField.id) {
911             case 0: // SUCCESS
912               if (schemeField.type == org.apache.thrift.protocol.TType.I32) {
913                 struct.success = iprot.readI32();
914                 struct.setSuccessIsSet(true);
915               } else { 
916                 org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
917               }
918               break;
919             default:
920               org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
921           }
922           iprot.readFieldEnd();
923         }
924         iprot.readStructEnd();
925 
926         // check for required fields of primitive type, which can't be checked in the validate method
927         struct.validate();
928       }
929 
930       public void write(org.apache.thrift.protocol.TProtocol oprot, add_result struct) throws org.apache.thrift.TException {
931         struct.validate();
932 
933         oprot.writeStructBegin(STRUCT_DESC);
934         oprot.writeFieldBegin(SUCCESS_FIELD_DESC);
935         oprot.writeI32(struct.success);
936         oprot.writeFieldEnd();
937         oprot.writeFieldStop();
938         oprot.writeStructEnd();
939       }
940 
941     }
942 
943     private static class add_resultTupleSchemeFactory implements SchemeFactory {
944       public add_resultTupleScheme getScheme() {
945         return new add_resultTupleScheme();
946       }
947     }
948 
949     private static class add_resultTupleScheme extends TupleScheme<add_result> {
950 
951       @Override
952       public void write(org.apache.thrift.protocol.TProtocol prot, add_result struct) throws org.apache.thrift.TException {
953         TTupleProtocol oprot = (TTupleProtocol) prot;
954         BitSet optionals = new BitSet();
955         if (struct.isSetSuccess()) {
956           optionals.set(0);
957         }
958         oprot.writeBitSet(optionals, 1);
959         if (struct.isSetSuccess()) {
960           oprot.writeI32(struct.success);
961         }
962       }
963 
964       @Override
965       public void read(org.apache.thrift.protocol.TProtocol prot, add_result struct) throws org.apache.thrift.TException {
966         TTupleProtocol iprot = (TTupleProtocol) prot;
967         BitSet incoming = iprot.readBitSet(1);
968         if (incoming.get(0)) {
969           struct.success = iprot.readI32();
970           struct.setSuccessIsSet(true);
971         }
972       }
973     }
974 
975   }
976 
977 }

 

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

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

 1 import org.apache.thrift.TException;
 2 
 3 
 4 public class AdditionServiceHandler implements AdditionService.Iface{
 5 
 6     @Override
 7     public int add(int n1, int n2) throws TException {
 8         // TODO Auto-generated method stub
 9         return n1 + n2;
10     }
11     
12 
13 }

4.写一个简单的服务器

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

 1 import org.apache.thrift.transport.TServerSocket;  
 2 import org.apache.thrift.transport.TServerTransport;  
 3 import org.apache.thrift.server.TServer;  
 4 import org.apache.thrift.server.TServer.Args;  
 5 import org.apache.thrift.server.TSimpleServer;  
 6    
 7 public class MyServer {  
 8    
 9  public static void StartsimpleServer(AdditionService.Processor<AdditionServiceHandler> processor) {  
10   try {  
11    TServerTransport serverTransport = new TServerSocket(9090);  
12    TServer server = new TSimpleServer(  
13      new Args(serverTransport).processor(processor));  
14    
15    // Use this for a multithreaded server  
16    // TServer server = new TThreadPoolServer(new  
17    // TThreadPoolServer.Args(serverTransport).processor(processor));  
18    
19    System.out.println("Starting the simple server...");  
20    server.serve();  
21   } catch (Exception e) {  
22    e.printStackTrace();  
23   }  
24  }  
25     
26  public static void main(String[] args) {  
27   StartsimpleServer(new AdditionService.Processor<AdditionServiceHandler>(new AdditionServiceHandler()));  
28  }  
29    
30 }

5.写一个简单的客户端

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

 1 import org.apache.thrift.TException;  
 2 import org.apache.thrift.protocol.TBinaryProtocol;  
 3 import org.apache.thrift.protocol.TProtocol;  
 4 import org.apache.thrift.transport.TSocket;  
 5 import org.apache.thrift.transport.TTransport;  
 6 import org.apache.thrift.transport.TTransportException;  
 7    
 8 public class AdditionClient {  
 9    
10  public static void main(String[] args) {  
11    
12   try {  
13    TTransport transport;  
14    
15    transport = new TSocket("localhost", 9090);  
16    transport.open();  
17    
18    TProtocol protocol = new TBinaryProtocol(transport);  
19    AdditionService.Client client = new AdditionService.Client(protocol);  
20    
21    System.out.println(client.add(100, 200));  
22    
23    transport.close();  
24   } catch (TTransportException e) {  
25    e.printStackTrace();  
26   } catch (TException x) {  
27    x.printStackTrace();  
28   }  
29  }  
30    
31 }

运行服务端代码(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

posted @ 2015-10-27 18:06  笨狗毒毒毒  阅读(570)  评论(0编辑  收藏  举报