thrift概述
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