JAVA RPC(二)序列化协议杂谈
序列化和反序列化作为Java里一个较为基础的知识点,大家心里也有那么几句要说的,但我相信很多小伙伴掌握的也就是那么几句而已,如果再深究问一下Java如何实现序列化和反序列化的,就可能不知所措了!遥记当年也被问了这一个问题,自信满满的说了一大堆,什么是序列化、什么是反序列化、什么场景的时候才会用到等,然后面试官说:那你能说一下序列化和反序列化底层是如何实现的吗?一脸懵逼,然后回家等通知!
1、什么是序列化和反序列化
(1)Java序列化是指把Java对象转换为字节序列的过程,而Java反序列化是指把字节序列恢复为Java对象的过程;
(2)序列化:对象序列化的最主要的用处就是在传递和保存对象的时候,保证对象的完整性和可传递性。序列化是把对象转换成有序字节流,以便在网络上传输或者保存在本地文件中。序列化后的字节流保存了Java对象的状态以及相关的描述信息。序列化机制的核心作用就是对象状态的保存与重建。
(3)反序列化:客户端从文件中或网络上获得序列化后的对象字节流后,根据字节流中所保存的对象状态及描述信息,通过反序列化重建对象。
(4)本质上讲,序列化就是把实体对象状态按照一定的格式写入到有序字节流,反序列化就是从有序字节流重建对象,恢复对象状态。
2、为什么需要序列化与反序列化
我们知道,当两个进程进行远程通信时,可以相互发送各种类型的数据,包括文本、图片、音频、视频等, 而这些数据都会以二进制序列的形式在网络上传送。
那么当两个Java进程进行通信时,能否实现进程间的对象传送呢?答案是可以的!如何做到呢?这就需要Java序列化与反序列化了!
换句话说,一方面,发送方需要把这个Java对象转换为字节序列,然后在网络上传送;另一方面,接收方需要从字节序列中恢复出Java对象。
当我们明晰了为什么需要Java序列化和反序列化后,我们很自然地会想Java序列化的好处。其好处一是实现了数据的持久化,通过序列化可以把数据永久地保存到硬盘上(通常存放在文件里),二是,利用序列化实现远程通信,即在网络上传送对象的字节序列。
总的来说可以归结为以下几点:
(1)永久性保存对象,保存对象的字节序列到本地文件或者数据库中;
(2)通过序列化以字节流的形式使对象在网络中进行传递和接收;
(3)通过序列化在进程间传递对象;
3、序列化算法一般会按步骤做如下事情:
(1)将对象实例相关的类元数据输出。
(2)递归地输出类的超类描述直到不再有超类。
(3)类元数据完了以后,开始从最顶层的超类开始输出对象实例的实际数据值。
(4)从上至下递归输出实例的数据
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;
}
}
原生序列化工具类
package util; import java.io.*;
import java.util.Arrays; public class SerializeUtil { /** 序列化对象
* @throws IOException */
public static byte[] serializeObject(Object object) throws IOException {
ByteArrayOutputStream saos = new ByteArrayOutputStream ();
ObjectOutputStream oos = new ObjectOutputStream(saos);
oos.writeObject(object);
oos.flush();
return saos.toByteArray();
} /** 反序列化对象
* @throws IOException
* @throws ClassNotFoundException */
public static Object deserializeObject(byte[] buf) throws IOException, ClassNotFoundException{
Object object=null;
ByteArrayInputStream sais=new ByteArrayInputStream(buf);
ObjectInputStream ois = new ObjectInputStream(sais);
object = ois.readObject();
return object;
}
}
由thrift脚本生成的User类
/**
* Autogenerated by Thrift Compiler (0.8.0)
*
* DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
* @generated
*/
package util.dtothrift; import org.apache.thrift.scheme.IScheme;
import org.apache.thrift.scheme.SchemeFactory;
import org.apache.thrift.scheme.StandardScheme; import org.apache.thrift.scheme.TupleScheme;
import org.apache.thrift.protocol.TTupleProtocol;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.util.HashMap;
import java.util.EnumMap;
import java.util.Set;
import java.util.HashSet;
import java.util.EnumSet;
import java.util.Collections;
import java.util.BitSet;
import java.nio.ByteBuffer;
import java.util.Arrays;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory; public class User implements org.apache.thrift.TBase<User, User._Fields>, java.io.Serializable, Cloneable {
private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("User"); 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);
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);
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); private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
static {
schemes.put(StandardScheme.class, new UserStandardSchemeFactory());
schemes.put(TupleScheme.class, new UserTupleSchemeFactory());
} public String str; // required
public int age; // required
public String address; // required /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
public enum _Fields implements org.apache.thrift.TFieldIdEnum {
STR((short)1, "str"),
AGE((short)2, "age"),
ADDRESS((short)3, "address"); private static final Map<String, _Fields> byName = new HashMap<String, _Fields>(); static {
for (_Fields field : EnumSet.allOf(_Fields.class)) {
byName.put(field.getFieldName(), field);
}
} /**
* Find the _Fields constant that matches fieldId, or null if its not found.
*/
public static _Fields findByThriftId(int fieldId) {
switch(fieldId) {
case 1: // STR
return STR;
case 2: // AGE
return AGE;
case 3: // ADDRESS
return ADDRESS;
default:
return null;
}
} /**
* Find the _Fields constant that matches fieldId, throwing an exception
* if it is not found.
*/
public static _Fields findByThriftIdOrThrow(int fieldId) {
_Fields fields = findByThriftId(fieldId);
if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
return fields;
} /**
* Find the _Fields constant that matches name, or null if its not found.
*/
public static _Fields findByName(String name) {
return byName.get(name);
} private final short _thriftId;
private final String _fieldName; _Fields(short thriftId, String fieldName) {
_thriftId = thriftId;
_fieldName = fieldName;
} public short getThriftFieldId() {
return _thriftId;
} public String getFieldName() {
return _fieldName;
}
} // isset id assignments
private static final int __AGE_ISSET_ID = 0;
private BitSet __isset_bit_vector = new BitSet(1);
public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
static {
Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
tmpMap.put(_Fields.STR, new org.apache.thrift.meta_data.FieldMetaData("str", org.apache.thrift.TFieldRequirementType.DEFAULT,
new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
tmpMap.put(_Fields.AGE, new org.apache.thrift.meta_data.FieldMetaData("age", org.apache.thrift.TFieldRequirementType.DEFAULT,
new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.I32)));
tmpMap.put(_Fields.ADDRESS, new org.apache.thrift.meta_data.FieldMetaData("address", org.apache.thrift.TFieldRequirementType.DEFAULT,
new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
metaDataMap = Collections.unmodifiableMap(tmpMap);
org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(User.class, metaDataMap);
} public User() {
} public User(
String str,
int age,
String address)
{
this();
this.str = str;
this.age = age;
setAgeIsSet(true);
this.address = address;
} /**
* Performs a deep copy on <i>other</i>.
*/
public User(User other) {
__isset_bit_vector.clear();
__isset_bit_vector.or(other.__isset_bit_vector);
if (other.isSetStr()) {
this.str = other.str;
}
this.age = other.age;
if (other.isSetAddress()) {
this.address = other.address;
}
} public User deepCopy() {
return new User(this);
} @Override
public void clear() {
this.str = null;
setAgeIsSet(false);
this.age = 0;
this.address = null;
} public String getStr() {
return this.str;
} public User setStr(String str) {
this.str = str;
return this;
} public void unsetStr() {
this.str = null;
} /** Returns true if field str is set (has been assigned a value) and false otherwise */
public boolean isSetStr() {
return this.str != null;
} public void setStrIsSet(boolean value) {
if (!value) {
this.str = null;
}
} public int getAge() {
return this.age;
} public User setAge(int age) {
this.age = age;
setAgeIsSet(true);
return this;
} public void unsetAge() {
__isset_bit_vector.clear(__AGE_ISSET_ID);
} /** Returns true if field age is set (has been assigned a value) and false otherwise */
public boolean isSetAge() {
return __isset_bit_vector.get(__AGE_ISSET_ID);
} public void setAgeIsSet(boolean value) {
__isset_bit_vector.set(__AGE_ISSET_ID, value);
} public String getAddress() {
return this.address;
} public User setAddress(String address) {
this.address = address;
return this;
} public void unsetAddress() {
this.address = null;
} /** Returns true if field address is set (has been assigned a value) and false otherwise */
public boolean isSetAddress() {
return this.address != null;
} public void setAddressIsSet(boolean value) {
if (!value) {
this.address = null;
}
} public void setFieldValue(_Fields field, Object value) {
switch (field) {
case STR:
if (value == null) {
unsetStr();
} else {
setStr((String)value);
}
break; case AGE:
if (value == null) {
unsetAge();
} else {
setAge((Integer)value);
}
break; case ADDRESS:
if (value == null) {
unsetAddress();
} else {
setAddress((String)value);
}
break; }
} public Object getFieldValue(_Fields field) {
switch (field) {
case STR:
return getStr(); case AGE:
return Integer.valueOf(getAge()); case ADDRESS:
return getAddress(); }
throw new IllegalStateException();
} /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
public boolean isSet(_Fields field) {
if (field == null) {
throw new IllegalArgumentException();
} switch (field) {
case STR:
return isSetStr();
case AGE:
return isSetAge();
case ADDRESS:
return isSetAddress();
}
throw new IllegalStateException();
} @Override
public boolean equals(Object that) {
if (that == null)
return false;
if (that instanceof User)
return this.equals((User)that);
return false;
} public boolean equals(User that) {
if (that == null)
return false; boolean this_present_str = true && this.isSetStr();
boolean that_present_str = true && that.isSetStr();
if (this_present_str || that_present_str) {
if (!(this_present_str && that_present_str))
return false;
if (!this.str.equals(that.str))
return false;
} boolean this_present_age = true;
boolean that_present_age = true;
if (this_present_age || that_present_age) {
if (!(this_present_age && that_present_age))
return false;
if (this.age != that.age)
return false;
} boolean this_present_address = true && this.isSetAddress();
boolean that_present_address = true && that.isSetAddress();
if (this_present_address || that_present_address) {
if (!(this_present_address && that_present_address))
return false;
if (!this.address.equals(that.address))
return false;
} return true;
} @Override
public int hashCode() {
return 0;
} public int compareTo(User other) {
if (!getClass().equals(other.getClass())) {
return getClass().getName().compareTo(other.getClass().getName());
} int lastComparison = 0;
User typedOther = (User)other; lastComparison = Boolean.valueOf(isSetStr()).compareTo(typedOther.isSetStr());
if (lastComparison != 0) {
return lastComparison;
}
if (isSetStr()) {
lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.str, typedOther.str);
if (lastComparison != 0) {
return lastComparison;
}
}
lastComparison = Boolean.valueOf(isSetAge()).compareTo(typedOther.isSetAge());
if (lastComparison != 0) {
return lastComparison;
}
if (isSetAge()) {
lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.age, typedOther.age);
if (lastComparison != 0) {
return lastComparison;
}
}
lastComparison = Boolean.valueOf(isSetAddress()).compareTo(typedOther.isSetAddress());
if (lastComparison != 0) {
return lastComparison;
}
if (isSetAddress()) {
lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.address, typedOther.address);
if (lastComparison != 0) {
return lastComparison;
}
}
return 0;
} public _Fields fieldForId(int fieldId) {
return _Fields.findByThriftId(fieldId);
} public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
} public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
} @Override
public String toString() {
StringBuilder sb = new StringBuilder("User(");
boolean first = true; sb.append("str:");
if (this.str == null) {
sb.append("null");
} else {
sb.append(this.str);
}
first = false;
if (!first) sb.append(", ");
sb.append("age:");
sb.append(this.age);
first = false;
if (!first) sb.append(", ");
sb.append("address:");
if (this.address == null) {
sb.append("null");
} else {
sb.append(this.address);
}
first = false;
sb.append(")");
return sb.toString();
} public void validate() throws org.apache.thrift.TException {
// check for required fields
} private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
try {
write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
} catch (org.apache.thrift.TException te) {
throw new java.io.IOException(te);
}
} private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
try {
// it doesn't seem like you should have to do this, but java serialization is wacky, and doesn't call the default constructor.
__isset_bit_vector = new BitSet(1);
read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
} catch (org.apache.thrift.TException te) {
throw new java.io.IOException(te);
}
} private static class UserStandardSchemeFactory implements SchemeFactory {
public UserStandardScheme getScheme() {
return new UserStandardScheme();
}
} private static class UserStandardScheme extends StandardScheme<User> { public void read(org.apache.thrift.protocol.TProtocol iprot, User struct) throws org.apache.thrift.TException {
org.apache.thrift.protocol.TField schemeField;
iprot.readStructBegin();
while (true)
{
schemeField = iprot.readFieldBegin();
if (schemeField.type == org.apache.thrift.protocol.TType.STOP) {
break;
}
switch (schemeField.id) {
case 1: // STR
if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
struct.str = iprot.readString();
struct.setStrIsSet(true);
} else {
org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
}
break;
case 2: // AGE
if (schemeField.type == org.apache.thrift.protocol.TType.I32) {
struct.age = iprot.readI32();
struct.setAgeIsSet(true);
} else {
org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
}
break;
case 3: // ADDRESS
if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
struct.address = iprot.readString();
struct.setAddressIsSet(true);
} else {
org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
}
break;
default:
org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
}
iprot.readFieldEnd();
}
iprot.readStructEnd(); // check for required fields of primitive type, which can't be checked in the validate method
struct.validate();
} public void write(org.apache.thrift.protocol.TProtocol oprot, User struct) throws org.apache.thrift.TException {
struct.validate(); oprot.writeStructBegin(STRUCT_DESC);
if (struct.str != null) {
oprot.writeFieldBegin(STR_FIELD_DESC);
oprot.writeString(struct.str);
oprot.writeFieldEnd();
}
oprot.writeFieldBegin(AGE_FIELD_DESC);
oprot.writeI32(struct.age);
oprot.writeFieldEnd();
if (struct.address != null) {
oprot.writeFieldBegin(ADDRESS_FIELD_DESC);
oprot.writeString(struct.address);
oprot.writeFieldEnd();
}
oprot.writeFieldStop();
oprot.writeStructEnd();
} } private static class UserTupleSchemeFactory implements SchemeFactory {
public UserTupleScheme getScheme() {
return new UserTupleScheme();
}
} private static class UserTupleScheme extends TupleScheme<User> { @Override
public void write(org.apache.thrift.protocol.TProtocol prot, User struct) throws org.apache.thrift.TException {
TTupleProtocol oprot = (TTupleProtocol) prot;
BitSet optionals = new BitSet();
if (struct.isSetStr()) {
optionals.set(0);
}
if (struct.isSetAge()) {
optionals.set(1);
}
if (struct.isSetAddress()) {
optionals.set(2);
}
oprot.writeBitSet(optionals, 3);
if (struct.isSetStr()) {
oprot.writeString(struct.str);
}
if (struct.isSetAge()) {
oprot.writeI32(struct.age);
}
if (struct.isSetAddress()) {
oprot.writeString(struct.address);
}
} @Override
public void read(org.apache.thrift.protocol.TProtocol prot, User struct) throws org.apache.thrift.TException {
TTupleProtocol iprot = (TTupleProtocol) prot;
BitSet incoming = iprot.readBitSet(3);
if (incoming.get(0)) {
struct.str = iprot.readString();
struct.setStrIsSet(true);
}
if (incoming.get(1)) {
struct.age = iprot.readI32();
struct.setAgeIsSet(true);
}
if (incoming.get(2)) {
struct.address = iprot.readString();
struct.setAddressIsSet(true);
}
}
} }
测试类
package util; import org.apache.thrift.TException;
import org.apache.thrift.protocol.TBinaryProtocol;
import org.apache.thrift.transport.TIOStreamTransport;
import org.apache.thrift.transport.TSocket;
import org.apache.thrift.transport.TTransport;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import util.dto.User; import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Arrays; public class SerializeTest { private final static Logger logger = LoggerFactory.getLogger ( SerializeTest.class ); public static void main(String[] args) throws IOException, ClassNotFoundException, TException { long a = System.currentTimeMillis ();
for (int i = 0; i < 100000; i++) {
User user = new User("姓名"+i,i,"北京市海淀区中关村大厦"+i);
byte[] b = SerializeUtil.serializeObject ( user );
//System.out.println (Arrays.toString ( b ));
User user1 = (User) SerializeUtil.deserializeObject ( b );
}
System.out.println (System.currentTimeMillis ()-a); long b = System.currentTimeMillis (); for (int i = 0; i < 100000; i++) {
util.dtothrift.User user = new util.dtothrift.User("姓名"+i,i,"北京市海淀区中关村大厦"+i);
ByteArrayOutputStream out = new ByteArrayOutputStream();
TTransport transport = new TIOStreamTransport (out);
TBinaryProtocol tp = new TBinaryProtocol(transport);
try {
user.write(tp);
} catch (TException e) {
e.printStackTrace();
}
byte[] bytes = out.toByteArray();
//System.out.println ( Arrays.toString ( bytes ));
util.dtothrift.User user1 = new util.dtothrift.User(); ByteArrayInputStream bis = new ByteArrayInputStream ( bytes);
TTransport transport1 = new TIOStreamTransport(bis);
TBinaryProtocol tp1 = new TBinaryProtocol(transport1);
user1.read (tp1);
}
System.out.println (System.currentTimeMillis ()-b);
} }
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
JAVA RPC(二)序列化协议杂谈的更多相关文章
- JAVA RPC (三) 之thrift序列化协议入门杂谈
首先抱歉让大家久等了,最近工作的原因,再加上自己维护koalas rpc利用的大部分时间,一直没腾出空来写这篇文章. 先放出来自研的企业级RPC框架源代码地址,上面有使用方式和部署环境说明,说环境部署 ...
- JAVA RPC (四) 之thrift序列化普通对象
先简单写一个thrift文件 本地通过thrift编译之后会生成一个java源文件.------编译口令 :thrift -gen java mytestrequest.thrift 编译后的源代码如 ...
- java RPC系列之二 HTTPINVOKER
java RPC系列之二 HTTPINVOKER 一.java RPC简单的汇总 java的RPC得到技术,基本包含以下几个,分别是:RMI(远程方法调用) .Caucho的Hessian 和 Bu ...
- 移动开发首页业界资讯移动应用平台技术专题 输入您要搜索的内容 基于Java Socket的自定义协议,实现Android与服务器的长连接(二)
在阅读本文前需要对socket以及自定义协议有一个基本的了解,可以先查看上一篇文章<基于Java Socket的自定义协议,实现Android与服务器的长连接(一)>学习相关的基础知识点. ...
- 对Java Serializable(序列化)的理解和总结(二)
遇到这个 Java Serializable 序列化这个接口,我们可能会有如下的问题a,什么叫序列化和反序列化 b,作用.为啥要实现这个 Serializable 接口,也就是为啥要序列化 c,ser ...
- 基于Netty的RPC架构学习笔记(九):自定义序列化协议
文章目录 为什么需要自定义序列化协议
- Dubbo 支持哪些序列化协议?
面试题 dubbo 支持哪些通信协议?支持哪些序列化协议?说一下 Hessian 的数据结构?PB 知道吗?为什么 PB 的效率是最高的? 面试官心理分析 上一个问题,说说 dubbo 的基本工作原理 ...
- JAVA RPC (六) 之手把手从零教你写一个生产级RPC之client的代理
首先对于RPC来讲,最主要的无非三点[SERVER IO模型].[序列化协议].[client连接池复用],之前的博客大家应该对thrift有一个大致的了解了,那么我们现在来说一说如何将thrift的 ...
- JAVA RPC(一)RPC入门
为什么要写这个RPC 市面上常见的RPC框架很多,grpc,motan,dubbo等,但是随着越来越多的元素加入,复杂的架构设计等因素似使得这些框架就想spring一样,虽然号称是轻量级,但是用起来却 ...
随机推荐
- Lua中的环境概念
[前言] Lua将其所有的全局变量保存在一个常规的table中,这个table称为“环境”.这种组织结构的优点在于,其一,不需要再为全局变量创造一种新的数据结构,因此简化了Lua的内部实现:另一个优点 ...
- Tomcat:3DES解密时中文乱码
情况说明:直接用main方法运行时是没有问题的,web程序一放入tomcat中就会出现解密时乱码. 解决办法: 在解密时,返回string时对数组需要指定UTF-8编码. public static ...
- 【原创】大叔问题定位分享(22)hive同时执行多个insert overwrite table只有1个可以执行
hive 2.1 一 问题 最近有一个场景,要向一个表的多个分区写数据,为了缩短执行时间,采用并发的方式,多个sql同时执行,分别写不同的分区,同时开启动态分区: set hive.exec.dyna ...
- Java的家庭记账本程序(K)
日期:2019.3.10 博客期:043 星期日 呕吼~这里是编程菜鸟小Master,今天加油的把第二个模板套用了,更改了许多的设定,我想这一个程序的网页版也就到这里结束了,下面是一部分的展示图,想要 ...
- 网络层HTPPS和HTTP的概念与区别
HTPPS和HTTP的概念 HTTPS(全称:Hypertext Transfer Protocol over Secure Socket Layer),是以安全为目标的HTTP通道,简单讲是HTTP ...
- java 获取用户ip
JSP里,获取客户端的IP地址的方法是: request.getRemoteAddr() 这种方法在大部分情况下都是有效的.但是在通过了Apache,Squid等反向代理软件就不能获取到客户端的真实I ...
- HTML转义字符&npsp;表示non-breaking space,unicode编码为u'\xa0',超出gbk编码范围?
0.目录 1.参考2.问题定位不间断空格的unicode表示为 u\xa0',超出gbk编码范围?3.如何处理.extract_first().replace(u'\xa0', u' ').strip ...
- [linux]主机访问虚拟机web服务(CentOS)
目的为了实现主机和虚拟机的通信,访问虚拟机中架设的web服务.按理说通过虚拟机ip + web服务端口,即可在浏览器访问虚拟机的web服务.但是由于CentOS的防火墙问题,对应web端口无法访问.通 ...
- CF1037E. Trips
题目链接 CF1037E. Trips 题解 每次删点后,对不满足要求的点拓扑 代码 #include<map> #include<queue> #include<vec ...
- [POJ2054]Color a Tree (并查集+贪心)
POJ终于修好啦 题意 和UVA1205是同一题,在洛谷上是紫题 有一棵树,需要给其所有节点染色,每个点染色所需的时间是一样的都是11.给每个点染色,还有一个开销“当前时间×ci×ci”,cici是每 ...