Thrift 객체 시리얼화, 역시리얼화 - 바이트 배열 분석
이 블로그는 Thrift 대상의 서열화, 반서열화 바이트 그룹과 Thrift 대상의 서열화, 반서열화 원리만 분석한다.기타 원본 분석은 따로 개설합니다~
준비 작업
Thrift 파일 정의
struct Person {
1: required i32 age;
2: required string name;
}
Java 코드 생성
thrift -r --gen java test.thrift
테스트 코드
@Test
public void testPerson() throws TException {
Person person = new Person().setAge(18).setName("yano");
System.out.println(person);
TSerializer serializer = new TSerializer();
byte[] bytes = serializer.serialize(person);
System.out.println(Arrays.toString(bytes));
Person parsePerson = new Person();
TDeserializer deserializer = new TDeserializer();
deserializer.deserialize(parsePerson, bytes);
System.out.println(parsePerson);
}
결과 내보내기
com.yano.nankai.spring.thrift.Person(age:18, name:yano)
[8, 0, 1, 0, 0, 0, 18, 11, 0, 2, 0, 0, 0, 4, 121, 97, 110, 111, 0]
com.yano.nankai.spring.thrift.Person(age:18, name:yano)
서열화 과정
상술한 테스트 용례는 먼저 Person 대상을 새로 만들었는데, 이 대상은 두 개의 필드만 있다.이어서 Thrift의 Tserializer를 호출하여 person 객체를 서열화합니다.
생성된 바이트 배열은 다음과 같습니다.
[8, 0, 1, 0, 0, 0, 18, 11, 0, 2, 0, 0, 0, 4, 121, 97, 110, 111, 0]
Tserializer 클래스의 Serialize 방법은 다음과 같습니다. 최종적으로 개인 대상의 write 방법을 호출했습니다.
public byte[] serialize(TBase base) throws TException {
this.baos_.reset();
base.write(this.protocol_);
return this.baos_.toByteArray();
}
Person 클래스의 write 방법:
public void write(TProtocol oprot) throws TException {
validate();
oprot.writeStructBegin(STRUCT_DESC);
oprot.writeFieldBegin(AGE_FIELD_DESC);
oprot.writeI32(this.age);
oprot.writeFieldEnd();
if (this.name != null) {
oprot.writeFieldBegin(NAME_FIELD_DESC);
oprot.writeString(this.name);
oprot.writeFieldEnd();
}
oprot.writeFieldStop();
oprot.writeStructEnd();
}
여기서 Tprotocol은 기본적으로 TBinary Protocol이고 write StructBegin () 및 write StructEnd () 방법은 비어 있습니다.
oprot.writeFieldBegin(AGE_FIELD_DESC);
TBinaryProtocol의 구체적인 구현은 다음과 같습니다.
public void writeFieldBegin(TField field) throws TException {
this.writeByte(field.type);
this.writeI16(field.id);
}
보시다시피, 우선 바이트 그룹을 byte에 써서 이 필드의 유형을 표시하고, 여기 있는 TFiled AGEFIELD_DESC:
private static final TField AGE_FIELD_DESC = new TField("age", TType.I32, (short)1);
thrift에서 정의된 첫 번째 필드는 다음과 같습니다.
1: required i32 age;
여기서 TType의 정의는 다음과 같습니다.
public final class TType {
public static final byte STOP = 0;
public static final byte VOID = 1;
public static final byte BOOL = 2;
public static final byte BYTE = 3;
public static final byte DOUBLE = 4;
public static final byte I16 = 6;
public static final byte I32 = 8;
public static final byte I64 = 10;
public static final byte STRING = 11;
public static final byte STRUCT = 12;
public static final byte MAP = 13;
public static final byte SET = 14;
public static final byte LIST = 15;
public static final byte ENUM = 16;
public TType() {
}
}
그러면 바이트 그룹의 첫 번째 요소는
i32
라는 유형으로 8이다.다음에 이 필드에 정의된 id를 쓸 것입니다.age 필드의 id는 1입니다. (여기는 두 바이트를 차지합니다.) 따라서 바이트 그룹의 다음 두 요소는 0, 1입니다.
name 필드에도 동일합니다.
출력된 바이트 배열의 각 값이 나타내는 의미:
8 // i32
0, 1 // id 1
0, 0, 0, 18 // id 1(age) , 4
11 // string
0, 2 // id 2(name)
0, 0, 0, 4 // name , 4
121, 97, 110, 111 // "yano" 4 ASCII ( UTF-8 )
0 //
역서열화 과정
역정렬된 문은 다음과 같습니다.
Person parsePerson = new Person();
TDeserializer deserializer = new TDeserializer();
deserializer.deserialize(parsePerson, bytes);
Person 클래스의 read 함수:
public void read(TProtocol iprot) throws TException {
TField field;
iprot.readStructBegin();
while (true)
{
field = iprot.readFieldBegin();
if (field.type == TType.STOP) {
break;
}
switch (field.id) {
case 1: // AGE
if (field.type == TType.I32) {
this.age = iprot.readI32();
setAgeIsSet(true);
} else {
TProtocolUtil.skip(iprot, field.type);
}
break;
case 2: // NAME
if (field.type == TType.STRING) {
this.name = iprot.readString();
} else {
TProtocolUtil.skip(iprot, field.type);
}
break;
default:
TProtocolUtil.skip(iprot, field.type);
}
iprot.readFieldEnd();
}
iprot.readStructEnd();
// check for required fields of primitive type, which can't be checked in the validate method
if (!isSetAge()) {
throw new TProtocolException("Required field 'age' was not found in serialized data! Struct: " + toString());
}
validate();
}
코드도 간단명료하다. 먼저 바이트 그룹에서 TField(5바이트, 1바이트 유형+4바이트 id)를 읽은 다음에 id에 따라 해당하는 필드에 값을 부여한다.
그중에 많은 세부 사항이 있으니 일일이 소개하지 않겠다.나도 원본 코드를 정확하게 쓰는 것보다 못하다.
Google Protocol Buffers와 비교
Google Protocol Buffers의 서열화 바이트 코드, Google Protocol Buffers 서열화 알고리즘 분석을 분석한 적이 있습니다.서열화된 바이트 배열의 차이가 여전히 매우 크다고 느낀다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
다양한 언어의 JSONJSON은 Javascript 표기법을 사용하여 데이터 구조를 레이아웃하는 데이터 형식입니다. 그러나 Javascript가 코드에서 이러한 구조를 나타낼 수 있는 유일한 언어는 아닙니다. 저는 일반적으로 '객체'{}...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.