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)
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

浙公网安备 33010602011771号