JAVA RPC(二)序列化協議雜談

      序列化和反序列化做爲Java裏一個較爲基礎的知識點,你們內心也有那麼幾句要說的,但我相信不少小夥伴掌握的也就是那麼幾句而已,若是再深究問一下Java如何實現序列化和反序列化的,就可能不知所措了!遙記當年也被問了這一個問題,自信滿滿的說了一大堆,什麼是序列化、什麼是反序列化、什麼場景的時候纔會用到等,而後面試官說:那你能說一下序列化和反序列化底層是如何實現的嗎?一臉懵逼,而後回家等通知!
 java

一、什麼是序列化和反序列化git

(1)Java序列化是指把Java對象轉換爲字節序列的過程,而Java反序列化是指把字節序列恢復爲Java對象的過程;面試

(2)序列化:對象序列化的最主要的用處就是在傳遞和保存對象的時候,保證對象的完整性和可傳遞性。序列化是把對象轉換成有序字節流,以便在網絡上傳輸或者保存在本地文件中。序列化後的字節流保存了Java對象的狀態以及相關的描述信息。序列化機制的核心做用就是對象狀態的保存與重建。算法

(3)反序列化:客戶端從文件中或網絡上得到序列化後的對象字節流後,根據字節流中所保存的對象狀態及描述信息,經過反序列化重建對象。數據庫

(4)本質上講,序列化就是把實體對象狀態按照必定的格式寫入到有序字節流,反序列化就是從有序字節流重建對象,恢復對象狀態。apache

 

二、爲何須要序列化與反序列化網絡

咱們知道,當兩個進程進行遠程通訊時,能夠相互發送各類類型的數據,包括文本、圖片、音頻、視頻等, 而這些數據都會以二進制序列的形式在網絡上傳送。app

那麼當兩個Java進程進行通訊時,可否實現進程間的對象傳送呢?答案是能夠的!如何作到呢?這就須要Java序列化與反序列化了!框架

換句話說,一方面,發送方須要把這個Java對象轉換爲字節序列,而後在網絡上傳送;另外一方面,接收方須要從字節序列中恢復出Java對象。koa

當咱們明晰了爲何須要Java序列化和反序列化後,咱們很天然地會想Java序列化的好處。其好處一是實現了數據的持久化,經過序列化能夠把數據永久地保存到硬盤上(一般存放在文件裏),二是,利用序列化實現遠程通訊,即在網絡上傳送對象的字節序列。

總的來講能夠歸結爲如下幾點:

(1)永久性保存對象,保存對象的字節序列到本地文件或者數據庫中;
(2)經過序列化以字節流的形式使對象在網絡中進行傳遞和接收;
(3)經過序列化在進程間傳遞對象;

三、序列化算法通常會按步驟作以下事情:

(1)將對象實例相關的類元數據輸出。
(2)遞歸地輸出類的超類描述直到再也不有超類。
(3)類元數據完了之後,開始從最頂層的超類開始輸出對象實例的實際數據值。
(4)從上至下遞歸輸出實例的數據

四、各類 Java 的序列化庫的性能比較測試結果

  • 專門針對Java語言的:Kryo,FST等等
  • 跨語言的:Protostuff,ProtoBuf,Thrift,Avro,MsgPack等等

圖片來源於網絡,能夠說明對原生序列化來說,其餘三方框架提供的序列化協議要快不少,因此咱們作RPC技術選型的時候,序列化協議這塊必定要摒棄原生序列化,去選擇一款本身熟悉的序列化協議來傳輸IO流。下面選擇作一個thrift序列化和原生序列化的對比結果。

 

原生序列化user類

package util.dto;

import java.io.Serializable;

public class User implements Serializable {
    private String name;
    private Integer integer;
    private String address;

    public User(String name, Integer integer, String address) {
        this.name = name;
        this.integer = integer;
        this.address = address;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getInteger() {
        return integer;
    }

    public void setInteger(Integer integer) {
        this.integer = integer;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }
}

 

原生序列化工具類

 1 package util;
 2 
 3 import java.io.*;
 4 import java.util.Arrays;
 5 
 6 public class SerializeUtil {
 7 
 8     /** 序列化對象
 9      * @throws IOException */
10     public static byte[] serializeObject(Object object) throws IOException {
11         ByteArrayOutputStream saos = new ByteArrayOutputStream ();
12         ObjectOutputStream oos = new ObjectOutputStream(saos);
13         oos.writeObject(object);
14         oos.flush();
15         return saos.toByteArray();
16     }
17 
18     /** 反序列化對象
19      * @throws IOException
20      * @throws ClassNotFoundException */
21     public static Object deserializeObject(byte[] buf) throws IOException, ClassNotFoundException{
22         Object object=null;
23         ByteArrayInputStream sais=new ByteArrayInputStream(buf);
24         ObjectInputStream ois = new ObjectInputStream(sais);
25         object = ois.readObject();
26         return object;
27     }
28 }

 

由thrift腳本生成的User類

  1 /**
  2  * Autogenerated by Thrift Compiler (0.8.0)
  3  *
  4  * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
  5  *  @generated
  6  */
  7 package util.dtothrift;
  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 User implements org.apache.thrift.TBase<User, User._Fields>, java.io.Serializable, Cloneable {
 31   private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("User");
 32 
 33   private static final org.apache.thrift.protocol.TField STR_FIELD_DESC = new org.apache.thrift.protocol.TField("str", org.apache.thrift.protocol.TType.STRING, (short)1);
 34   private static final org.apache.thrift.protocol.TField AGE_FIELD_DESC = new org.apache.thrift.protocol.TField("age", org.apache.thrift.protocol.TType.I32, (short)2);
 35   private static final org.apache.thrift.protocol.TField ADDRESS_FIELD_DESC = new org.apache.thrift.protocol.TField("address", org.apache.thrift.protocol.TType.STRING, (short)3);
 36 
 37   private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
 38   static {
 39     schemes.put(StandardScheme.class, new UserStandardSchemeFactory());
 40     schemes.put(TupleScheme.class, new UserTupleSchemeFactory());
 41   }
 42 
 43   public String str; // required
 44   public int age; // required
 45   public String address; // required
 46 
 47   /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
 48   public enum _Fields implements org.apache.thrift.TFieldIdEnum {
 49     STR((short)1, "str"),
 50     AGE((short)2, "age"),
 51     ADDRESS((short)3, "address");
 52 
 53     private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();
 54 
 55     static {
 56       for (_Fields field : EnumSet.allOf(_Fields.class)) {
 57         byName.put(field.getFieldName(), field);
 58       }
 59     }
 60 
 61     /**
 62      * Find the _Fields constant that matches fieldId, or null if its not found.
 63      */
 64     public static _Fields findByThriftId(int fieldId) {
 65       switch(fieldId) {
 66         case 1: // STR
 67           return STR;
 68         case 2: // AGE
 69           return AGE;
 70         case 3: // ADDRESS
 71           return ADDRESS;
 72         default:
 73           return null;
 74       }
 75     }
 76 
 77     /**
 78      * Find the _Fields constant that matches fieldId, throwing an exception
 79      * if it is not found.
 80      */
 81     public static _Fields findByThriftIdOrThrow(int fieldId) {
 82       _Fields fields = findByThriftId(fieldId);
 83       if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
 84       return fields;
 85     }
 86 
 87     /**
 88      * Find the _Fields constant that matches name, or null if its not found.
 89      */
 90     public static _Fields findByName(String name) {
 91       return byName.get(name);
 92     }
 93 
 94     private final short _thriftId;
 95     private final String _fieldName;
 96 
 97     _Fields(short thriftId, String fieldName) {
 98       _thriftId = thriftId;
 99       _fieldName = fieldName;
100     }
101 
102     public short getThriftFieldId() {
103       return _thriftId;
104     }
105 
106     public String getFieldName() {
107       return _fieldName;
108     }
109   }
110 
111   // isset id assignments
112   private static final int __AGE_ISSET_ID = 0;
113   private BitSet __isset_bit_vector = new BitSet(1);
114   public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
115   static {
116     Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
117     tmpMap.put(_Fields.STR, new org.apache.thrift.meta_data.FieldMetaData("str", org.apache.thrift.TFieldRequirementType.DEFAULT, 
118         new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
119     tmpMap.put(_Fields.AGE, new org.apache.thrift.meta_data.FieldMetaData("age", org.apache.thrift.TFieldRequirementType.DEFAULT, 
120         new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.I32)));
121     tmpMap.put(_Fields.ADDRESS, new org.apache.thrift.meta_data.FieldMetaData("address", org.apache.thrift.TFieldRequirementType.DEFAULT, 
122         new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
123     metaDataMap = Collections.unmodifiableMap(tmpMap);
124     org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(User.class, metaDataMap);
125   }
126 
127   public User() {
128   }
129 
130   public User(
131     String str,
132     int age,
133     String address)
134   {
135     this();
136     this.str = str;
137     this.age = age;
138     setAgeIsSet(true);
139     this.address = address;
140   }
141 
142   /**
143    * Performs a deep copy on <i>other</i>.
144    */
145   public User(User other) {
146     __isset_bit_vector.clear();
147     __isset_bit_vector.or(other.__isset_bit_vector);
148     if (other.isSetStr()) {
149       this.str = other.str;
150     }
151     this.age = other.age;
152     if (other.isSetAddress()) {
153       this.address = other.address;
154     }
155   }
156 
157   public User deepCopy() {
158     return new User(this);
159   }
160 
161   @Override
162   public void clear() {
163     this.str = null;
164     setAgeIsSet(false);
165     this.age = 0;
166     this.address = null;
167   }
168 
169   public String getStr() {
170     return this.str;
171   }
172 
173   public User setStr(String str) {
174     this.str = str;
175     return this;
176   }
177 
178   public void unsetStr() {
179     this.str = null;
180   }
181 
182   /** Returns true if field str is set (has been assigned a value) and false otherwise */
183   public boolean isSetStr() {
184     return this.str != null;
185   }
186 
187   public void setStrIsSet(boolean value) {
188     if (!value) {
189       this.str = null;
190     }
191   }
192 
193   public int getAge() {
194     return this.age;
195   }
196 
197   public User setAge(int age) {
198     this.age = age;
199     setAgeIsSet(true);
200     return this;
201   }
202 
203   public void unsetAge() {
204     __isset_bit_vector.clear(__AGE_ISSET_ID);
205   }
206 
207   /** Returns true if field age is set (has been assigned a value) and false otherwise */
208   public boolean isSetAge() {
209     return __isset_bit_vector.get(__AGE_ISSET_ID);
210   }
211 
212   public void setAgeIsSet(boolean value) {
213     __isset_bit_vector.set(__AGE_ISSET_ID, value);
214   }
215 
216   public String getAddress() {
217     return this.address;
218   }
219 
220   public User setAddress(String address) {
221     this.address = address;
222     return this;
223   }
224 
225   public void unsetAddress() {
226     this.address = null;
227   }
228 
229   /** Returns true if field address is set (has been assigned a value) and false otherwise */
230   public boolean isSetAddress() {
231     return this.address != null;
232   }
233 
234   public void setAddressIsSet(boolean value) {
235     if (!value) {
236       this.address = null;
237     }
238   }
239 
240   public void setFieldValue(_Fields field, Object value) {
241     switch (field) {
242     case STR:
243       if (value == null) {
244         unsetStr();
245       } else {
246         setStr((String)value);
247       }
248       break;
249 
250     case AGE:
251       if (value == null) {
252         unsetAge();
253       } else {
254         setAge((Integer)value);
255       }
256       break;
257 
258     case ADDRESS:
259       if (value == null) {
260         unsetAddress();
261       } else {
262         setAddress((String)value);
263       }
264       break;
265 
266     }
267   }
268 
269   public Object getFieldValue(_Fields field) {
270     switch (field) {
271     case STR:
272       return getStr();
273 
274     case AGE:
275       return Integer.valueOf(getAge());
276 
277     case ADDRESS:
278       return getAddress();
279 
280     }
281     throw new IllegalStateException();
282   }
283 
284   /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
285   public boolean isSet(_Fields field) {
286     if (field == null) {
287       throw new IllegalArgumentException();
288     }
289 
290     switch (field) {
291     case STR:
292       return isSetStr();
293     case AGE:
294       return isSetAge();
295     case ADDRESS:
296       return isSetAddress();
297     }
298     throw new IllegalStateException();
299   }
300 
301   @Override
302   public boolean equals(Object that) {
303     if (that == null)
304       return false;
305     if (that instanceof User)
306       return this.equals((User)that);
307     return false;
308   }
309 
310   public boolean equals(User that) {
311     if (that == null)
312       return false;
313 
314     boolean this_present_str = true && this.isSetStr();
315     boolean that_present_str = true && that.isSetStr();
316     if (this_present_str || that_present_str) {
317       if (!(this_present_str && that_present_str))
318         return false;
319       if (!this.str.equals(that.str))
320         return false;
321     }
322 
323     boolean this_present_age = true;
324     boolean that_present_age = true;
325     if (this_present_age || that_present_age) {
326       if (!(this_present_age && that_present_age))
327         return false;
328       if (this.age != that.age)
329         return false;
330     }
331 
332     boolean this_present_address = true && this.isSetAddress();
333     boolean that_present_address = true && that.isSetAddress();
334     if (this_present_address || that_present_address) {
335       if (!(this_present_address && that_present_address))
336         return false;
337       if (!this.address.equals(that.address))
338         return false;
339     }
340 
341     return true;
342   }
343 
344   @Override
345   public int hashCode() {
346     return 0;
347   }
348 
349   public int compareTo(User other) {
350     if (!getClass().equals(other.getClass())) {
351       return getClass().getName().compareTo(other.getClass().getName());
352     }
353 
354     int lastComparison = 0;
355     User typedOther = (User)other;
356 
357     lastComparison = Boolean.valueOf(isSetStr()).compareTo(typedOther.isSetStr());
358     if (lastComparison != 0) {
359       return lastComparison;
360     }
361     if (isSetStr()) {
362       lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.str, typedOther.str);
363       if (lastComparison != 0) {
364         return lastComparison;
365       }
366     }
367     lastComparison = Boolean.valueOf(isSetAge()).compareTo(typedOther.isSetAge());
368     if (lastComparison != 0) {
369       return lastComparison;
370     }
371     if (isSetAge()) {
372       lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.age, typedOther.age);
373       if (lastComparison != 0) {
374         return lastComparison;
375       }
376     }
377     lastComparison = Boolean.valueOf(isSetAddress()).compareTo(typedOther.isSetAddress());
378     if (lastComparison != 0) {
379       return lastComparison;
380     }
381     if (isSetAddress()) {
382       lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.address, typedOther.address);
383       if (lastComparison != 0) {
384         return lastComparison;
385       }
386     }
387     return 0;
388   }
389 
390   public _Fields fieldForId(int fieldId) {
391     return _Fields.findByThriftId(fieldId);
392   }
393 
394   public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
395     schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
396   }
397 
398   public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
399     schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
400   }
401 
402   @Override
403   public String toString() {
404     StringBuilder sb = new StringBuilder("User(");
405     boolean first = true;
406 
407     sb.append("str:");
408     if (this.str == null) {
409       sb.append("null");
410     } else {
411       sb.append(this.str);
412     }
413     first = false;
414     if (!first) sb.append(", ");
415     sb.append("age:");
416     sb.append(this.age);
417     first = false;
418     if (!first) sb.append(", ");
419     sb.append("address:");
420     if (this.address == null) {
421       sb.append("null");
422     } else {
423       sb.append(this.address);
424     }
425     first = false;
426     sb.append(")");
427     return sb.toString();
428   }
429 
430   public void validate() throws org.apache.thrift.TException {
431     // check for required fields
432   }
433 
434   private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
435     try {
436       write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
437     } catch (org.apache.thrift.TException te) {
438       throw new java.io.IOException(te);
439     }
440   }
441 
442   private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
443     try {
444       // it doesn't seem like you should have to do this, but java serialization is wacky, and doesn't call the default constructor.
445       __isset_bit_vector = new BitSet(1);
446       read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
447     } catch (org.apache.thrift.TException te) {
448       throw new java.io.IOException(te);
449     }
450   }
451 
452   private static class UserStandardSchemeFactory implements SchemeFactory {
453     public UserStandardScheme getScheme() {
454       return new UserStandardScheme();
455     }
456   }
457 
458   private static class UserStandardScheme extends StandardScheme<User> {
459 
460     public void read(org.apache.thrift.protocol.TProtocol iprot, User struct) throws org.apache.thrift.TException {
461       org.apache.thrift.protocol.TField schemeField;
462       iprot.readStructBegin();
463       while (true)
464       {
465         schemeField = iprot.readFieldBegin();
466         if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
467           break;
468         }
469         switch (schemeField.id) {
470           case 1: // STR
471             if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
472               struct.str = iprot.readString();
473               struct.setStrIsSet(true);
474             } else { 
475               org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
476             }
477             break;
478           case 2: // AGE
479             if (schemeField.type == org.apache.thrift.protocol.TType.I32) {
480               struct.age = iprot.readI32();
481               struct.setAgeIsSet(true);
482             } else { 
483               org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
484             }
485             break;
486           case 3: // ADDRESS
487             if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
488               struct.address = iprot.readString();
489               struct.setAddressIsSet(true);
490             } else { 
491               org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
492             }
493             break;
494           default:
495             org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
496         }
497         iprot.readFieldEnd();
498       }
499       iprot.readStructEnd();
500 
501       // check for required fields of primitive type, which can't be checked in the validate method
502       struct.validate();
503     }
504 
505     public void write(org.apache.thrift.protocol.TProtocol oprot, User struct) throws org.apache.thrift.TException {
506       struct.validate();
507 
508       oprot.writeStructBegin(STRUCT_DESC);
509       if (struct.str != null) {
510         oprot.writeFieldBegin(STR_FIELD_DESC);
511         oprot.writeString(struct.str);
512         oprot.writeFieldEnd();
513       }
514       oprot.writeFieldBegin(AGE_FIELD_DESC);
515       oprot.writeI32(struct.age);
516       oprot.writeFieldEnd();
517       if (struct.address != null) {
518         oprot.writeFieldBegin(ADDRESS_FIELD_DESC);
519         oprot.writeString(struct.address);
520         oprot.writeFieldEnd();
521       }
522       oprot.writeFieldStop();
523       oprot.writeStructEnd();
524     }
525 
526   }
527 
528   private static class UserTupleSchemeFactory implements SchemeFactory {
529     public UserTupleScheme getScheme() {
530       return new UserTupleScheme();
531     }
532   }
533 
534   private static class UserTupleScheme extends TupleScheme<User> {
535 
536     @Override
537     public void write(org.apache.thrift.protocol.TProtocol prot, User struct) throws org.apache.thrift.TException {
538       TTupleProtocol oprot = (TTupleProtocol) prot;
539       BitSet optionals = new BitSet();
540       if (struct.isSetStr()) {
541         optionals.set(0);
542       }
543       if (struct.isSetAge()) {
544         optionals.set(1);
545       }
546       if (struct.isSetAddress()) {
547         optionals.set(2);
548       }
549       oprot.writeBitSet(optionals, 3);
550       if (struct.isSetStr()) {
551         oprot.writeString(struct.str);
552       }
553       if (struct.isSetAge()) {
554         oprot.writeI32(struct.age);
555       }
556       if (struct.isSetAddress()) {
557         oprot.writeString(struct.address);
558       }
559     }
560 
561     @Override
562     public void read(org.apache.thrift.protocol.TProtocol prot, User struct) throws org.apache.thrift.TException {
563       TTupleProtocol iprot = (TTupleProtocol) prot;
564       BitSet incoming = iprot.readBitSet(3);
565       if (incoming.get(0)) {
566         struct.str = iprot.readString();
567         struct.setStrIsSet(true);
568       }
569       if (incoming.get(1)) {
570         struct.age = iprot.readI32();
571         struct.setAgeIsSet(true);
572       }
573       if (incoming.get(2)) {
574         struct.address = iprot.readString();
575         struct.setAddressIsSet(true);
576       }
577     }
578   }
579 
580 }

 

測試類

 1 package util;
 2 
 3 import org.apache.thrift.TException;
 4 import org.apache.thrift.protocol.TBinaryProtocol;
 5 import org.apache.thrift.transport.TIOStreamTransport;
 6 import org.apache.thrift.transport.TSocket;
 7 import org.apache.thrift.transport.TTransport;
 8 import org.slf4j.Logger;
 9 import org.slf4j.LoggerFactory;
10 import util.dto.User;
11 
12 import java.io.ByteArrayInputStream;
13 import java.io.ByteArrayOutputStream;
14 import java.io.IOException;
15 import java.util.Arrays;
16 
17 public class SerializeTest {
18 
19     private final static Logger logger = LoggerFactory.getLogger ( SerializeTest.class );
20 
21     public static void main(String[] args) throws IOException, ClassNotFoundException, TException {
22 
23         long a = System.currentTimeMillis ();
24         for (int i = 0; i < 100000; i++) {
25             User user = new User("姓名"+i,i,"北京市海淀區中關村大廈"+i);
26             byte[] b = SerializeUtil.serializeObject ( user );
27             //System.out.println (Arrays.toString ( b ));
28             User user1 = (User) SerializeUtil.deserializeObject ( b );
29         }
30         System.out.println (System.currentTimeMillis ()-a);
31 
32         long b = System.currentTimeMillis ();
33 
34         for (int i = 0; i < 100000; i++) {
35             util.dtothrift.User user = new util.dtothrift.User("姓名"+i,i,"北京市海淀區中關村大廈"+i);
36             ByteArrayOutputStream out = new ByteArrayOutputStream();
37             TTransport transport = new TIOStreamTransport (out);
38             TBinaryProtocol tp = new TBinaryProtocol(transport);
39             try {
40                 user.write(tp);
41             } catch (TException e) {
42                 e.printStackTrace();
43             }
44             byte[] bytes = out.toByteArray();
45             //System.out.println ( Arrays.toString ( bytes ));
46             util.dtothrift.User user1 = new util.dtothrift.User();
47 
48             ByteArrayInputStream bis = new ByteArrayInputStream (  bytes);
49             TTransport transport1 = new TIOStreamTransport(bis);
50             TBinaryProtocol tp1 = new TBinaryProtocol(transport1);
51             user1.read (tp1);
52         }
53         System.out.println (System.currentTimeMillis ()-b);
54     }
55 
56 }

 

10萬次序列化和反序列化的結果對比

 

由上圖能夠看出,採用facebook的序列化協議要比原生jdk序列化協議在10萬次序列化和反序列化操做中的時間快不少,而且thrift沒有原生序列化的那麼多的要求,咱們來看看原生序列化和thrift序列化的輸入結果都是什麼,打開 System.out.println ( Arrays.toString ( bytes ))代碼後

jdk 輸出流

[-84, -19, 0, 5, 115, 114, 0, 13, 117, 116, 105, 108, 46, 100, 116, 111, 46, 85, 115, 101, 114, -45, 124, 21, -36, 14, -39, -44, 35, 2, 0, 3, 76, 0, 7, 97, 100, 100, 114, 101, 115, 115, 116, 0, 18, 76, 106, 97, 118, 97, 47, 108, 97, 110, 103, 47, 83, 116, 114, 105, 110, 103, 59, 76, 0, 7, 105, 110, 116, 101, 103, 101, 114, 116, 0, 19, 76, 106, 97, 118, 97, 47, 108, 97, 110, 103, 47, 73, 110, 116, 101, 103, 101, 114, 59, 76, 0, 4, 110, 97, 109, 101, 113, 0, 126, 0, 1, 120, 112, 116, 0, 34, -27, -116, -105, -28, -70, -84, -27, -72, -126, -26, -75, -73, -26, -73, -128, -27, -116, -70, -28, -72, -83, -27, -123, -77, -26, -99, -111, -27, -92, -89, -27, -114, -90, 48, 115, 114, 0, 17, 106, 97, 118, 97, 46, 108, 97, 110, 103, 46, 73, 110, 116, 101, 103, 101, 114, 18, -30, -96, -92, -9, -127, -121, 56, 2, 0, 1, 73, 0, 5, 118, 97, 108, 117, 101, 120, 114, 0, 16, 106, 97, 118, 97, 46, 108, 97, 110, 103, 46, 78, 117, 109, 98, 101, 114, -122, -84, -107, 29, 11, -108, -32, -117, 2, 0, 0, 120, 112, 0, 0, 0, 0, 116, 0, 7, -27, -89, -109, -27, -112, -115, 48]

thrift輸出流

[11, 0, 1, 0, 0, 0, 7, -27, -89, -109, -27, -112, -115, 48, 8, 0, 2, 0, 0, 0, 0, 11, 0, 3, 0, 0, 0, 34, -27, -116, -105, -28, -70, -84, -27, -72, -126, -26, -75, -73, -26, -73, -128, -27, -116, -70, -28, -72, -83, -27, -123, -77, -26, -99, -111, -27, -92, -89, -27, -114, -90, 48, 0]

由此能夠看出jdk的輸出流比thrift的輸出流多不少,由於jdk原生序列化對方法棧信息,類信息等作了詳細的記錄,其實這些信息對於RPC來講不是傳輸必要參數,因此精簡序列化IO流大小在傳輸中十分關鍵

本章對序列化進行了簡單的概述,你們能夠針對個人上面代碼進行測試。

 

高級java交流羣:825199617

歡迎熱愛源碼志同道合的朋友加入。

koalas rpc源碼地址https://gitee.com/a1234567891/koalas-rpc

相關文章
相關標籤/搜索