SparkStreaming - Kryo框架的關(guān)鍵功能

1.概述

Kryo是一個(gè)Java序列化框架欺嗤。本文將嘗試著探索Kryo框架的關(guān)鍵功能,并用示例展示出來(lái)。

2. Maven依賴

<dependency>
    <groupId>com.esotericsoftware</groupId>
    <artifactId>kryo</artifactId>
    <version>4.0.1</version>
</dependency>

可以在Maven Central上找到最新版本圃阳。

3. Kryo基礎(chǔ)

Kryo的工作方式孽文,以及如何使用它來(lái)序列化和反序列化對(duì)象驻襟。

3.1 介紹

該框架將Kryo類作為其所有功能的主要入口點(diǎn)。

此類協(xié)調(diào)序列化過(guò)程芋哭,并將將對(duì)象轉(zhuǎn)換為字節(jié)形式沉衣。字節(jié)準(zhǔn)備好后,將使用Output對(duì)象將它們寫入流减牺。這樣豌习,它們可以存儲(chǔ)在文件,數(shù)據(jù)庫(kù)中或通過(guò)網(wǎng)絡(luò)傳輸拔疚。稍后肥隆,當(dāng)需要該對(duì)象時(shí),將使用Input實(shí)例讀取這些字節(jié)并將其解碼為Java對(duì)象稚失。

3.2 序列化對(duì)象

首先初始化測(cè)試用例的一些變量:

@Before
public void init() {
    kryo = new Kryo();
    output = new Output(new FileOutputStream("file.dat"));
    input = new Input(new FileInputStream("file.dat"));
}

使用Kryo寫和讀對(duì)象:

@Test
public void givenObject_whenSerializing_thenReadCorrectly() {
    Object someObject = "Some string";
 
    kryo.writeClassAndObject(output, someObject);
    output.close();
 
    Object theObject = kryo.readClassAndObject(input);
    input.close();
 
    assertEquals(theObject, "Some string");
}

請(qǐng)注意對(duì)close()方法的調(diào)用栋艳。這是必需的,因?yàn)?em>Output和Input類分別繼承自OutputStreamInputStream墩虹。

序列化多個(gè)對(duì)象同樣簡(jiǎn)單:

@Test
public void givenObjects_whenSerializing_thenReadCorrectly() {
    String someString = "Multiple Objects";
    Date someDate = new Date(915170400000L);
 
    kryo.writeObject(output, someString);
    kryo.writeObject(output, someDate);
    output.close();
 
    String readString = kryo.readObject(input, String.class);
    Date readDate = kryo.readObject(input, Date.class);
    input.close();
 
    assertEquals(readString, "Multiple Objects");
    assertEquals(readDate.getTime(), 915170400000L);
}

請(qǐng)注意嘱巾,我們正在將適當(dāng)?shù)念悅鬟f給readObject()方法憨琳,這使我們的代碼無(wú)需轉(zhuǎn)換。

4.序列化器

在本節(jié)中旬昭,我們將顯示哪些序列化器已經(jīng)可用篙螟,然后我們將創(chuàng)建自己的序列化器。

4.1 默認(rèn)序列化器

當(dāng)Kryo序列化一個(gè)對(duì)象時(shí)问拘,它將創(chuàng)建一個(gè)先前注冊(cè)的Serializer類的實(shí)例遍略,以將其轉(zhuǎn)換為字節(jié)。這些稱為默認(rèn)序列化器骤坐,無(wú)需我們?nèi)魏卧O(shè)置即可使用绪杏。

該庫(kù)已經(jīng)提供了幾個(gè)處理列表,映射纽绍,枚舉等的序列化器蕾久。如果找不到給定類的序列化器,則使用FieldSerializer拌夏,它可以處理幾乎任何類型的對(duì)象僧著。

讓我們看看它的樣子。首先障簿,讓我們創(chuàng)建一個(gè)Person類:

public class Person {
    private String name = "John Doe";
    private int age = 18;
    private Date birthDate = new Date(933191282821L);
 
    // standard constructors, getters, and setters
}

現(xiàn)在盹愚,讓我們從此類中編寫一個(gè)對(duì)象,然后將其讀回:

@Test
public void givenPerson_whenSerializing_thenReadCorrectly() {
    Person person = new Person();
 
    kryo.writeObject(output, person);
    output.close();
 
    Person readPerson = kryo.readObject(input, Person.class);
    input.close();
 
    assertEquals(readPerson.getName(), "John Doe");
}

注意站故,由于FieldSerializer是為我們自動(dòng)創(chuàng)建的皆怕,因此無(wú)需指定任何內(nèi)容來(lái)序列化Person對(duì)象。

4.2 自定義序列化器

如果需要對(duì)序列化過(guò)程進(jìn)行更多控制西篓,則有兩個(gè)選擇愈腾;我們可以編寫自己的Serializer類,并在Kryo中注冊(cè)它污淋,或者讓該類自行處理序列化顶滩。

為了演示第一個(gè)選項(xiàng),讓我們創(chuàng)建一個(gè)擴(kuò)展Serializer的類:

public class PersonSerializer extends Serializer<Person> {
 
    public void write(Kryo kryo, Output output, Person object) {
        output.writeString(object.getName());
        output.writeLong(object.getBirthDate().getTime());
    }
 
    public Person read(Kryo kryo, Input input, Class<Person> type) {
        Person person = new Person();
        person.setName(input.readString());
        long birthDate = input.readLong();
        person.setBirthDate(new Date(birthDate));
        person.setAge(calculateAge(birthDate));
        return person;
    }
 
    private int calculateAge(long birthDate) {
        // Some custom logic
        return 18;
    }
}

現(xiàn)在寸爆,讓我們對(duì)其進(jìn)行測(cè)試:

@Test
public void givenPerson_whenUsingCustomSerializer_thenReadCorrectly() {
    Person person = new Person();
    person.setAge(0);
     
    kryo.register(Person.class, new PersonSerializer());
    kryo.writeObject(output, person);
    output.close();
 
    Person readPerson = kryo.readObject(input, Person.class);
    input.close();
 
    assertEquals(readPerson.getName(), "John Doe");
    assertEquals(readPerson.getAge(), 18);
}

請(qǐng)注意,即使我們之前將年齡字段設(shè)置為0盐欺,年齡字段也等于18赁豆。

我們還可以使用@DefaultSerializer注釋讓Kryo知道我們每次需要處理Person對(duì)象時(shí)都想使用PersonSerializer。這有助于避免調(diào)用register()方法:

@DefaultSerializer(PersonSerializer.class)
public class Person implements KryoSerializable {
    // ...
}

對(duì)于第二個(gè)選項(xiàng)冗美,讓我們修改Person類以擴(kuò)展KryoSerializable接口:

public class Person implements KryoSerializable {
    // ...
 
    public void write(Kryo kryo, Output output) {
        output.writeString(name);
        // ...
    }
 
    public void read(Kryo kryo, Input input) {
        name = input.readString();
        // ...
    }
}

由于此選項(xiàng)的測(cè)試用例等于前一個(gè)魔种,因此此處不包括。但是粉洼,您可以在本文的源代碼中找到它节预。

4.3 Java序列化器

在零星的情況下叶摄,Kryo將無(wú)法序列化一個(gè)類。如果發(fā)生這種情況安拟,并且不能編寫自定義序列化程序蛤吓,則可以使用JavaSerializer使用標(biāo)準(zhǔn)的Java序列化機(jī)制。這就要求該類照常實(shí)現(xiàn)Serializable接口糠赦。

這是一個(gè)使用上述序列化器的示例:

public class ComplexObject implements Serializable {
    private String name = "Bael";
     
    // standard getters and setters
}
@Test
public void givenJavaSerializable_whenSerializing_thenReadCorrectly() {
    ComplexClass complexObject = new ComplexClass();
    kryo.register(ComplexClass.class, new JavaSerializer());
 
    kryo.writeObject(output, complexObject);
    output.close();
 
    ComplexClass readComplexObject = kryo.readObject(input, ComplexClass.class);
    input.close();
 
    assertEquals(readComplexObject.getName(), "Bael");
}

5.結(jié)論

以上探索了Kryo庫(kù)最關(guān)鍵的功能会傲。序列化了多個(gè)簡(jiǎn)單對(duì)象,并使用FieldSerializer類處理自定義對(duì)象拙泽。我們還創(chuàng)建了一個(gè)自定義序列化程序淌山,并演示了如何在需要時(shí)退回到標(biāo)準(zhǔn)Java序列化機(jī)制。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
禁止轉(zhuǎn)載顾瞻,如需轉(zhuǎn)載請(qǐng)通過(guò)簡(jiǎn)信或評(píng)論聯(lián)系作者泼疑。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市荷荤,隨后出現(xiàn)的幾起案子王浴,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,406評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件烟央,死亡現(xiàn)場(chǎng)離奇詭異薛夜,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)钞啸,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,732評(píng)論 3 393
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)喇潘,“玉大人体斩,你說(shuō)我怎么就攤上這事∮钡停” “怎么了絮吵?”我有些...
    開封第一講書人閱讀 163,711評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)忱屑。 經(jīng)常有香客問我蹬敲,道長(zhǎng),這世上最難降的妖魔是什么莺戒? 我笑而不...
    開封第一講書人閱讀 58,380評(píng)論 1 293
  • 正文 為了忘掉前任伴嗡,我火速辦了婚禮,結(jié)果婚禮上从铲,老公的妹妹穿的比我還像新娘瘪校。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,432評(píng)論 6 392
  • 文/花漫 我一把揭開白布阱扬。 她就那樣靜靜地躺著泣懊,像睡著了一般。 火紅的嫁衣襯著肌膚如雪麻惶。 梳的紋絲不亂的頭發(fā)上馍刮,一...
    開封第一講書人閱讀 51,301評(píng)論 1 301
  • 那天,我揣著相機(jī)與錄音用踩,去河邊找鬼渠退。 笑死,一個(gè)胖子當(dāng)著我的面吹牛脐彩,可吹牛的內(nèi)容都是我干的碎乃。 我是一名探鬼主播,決...
    沈念sama閱讀 40,145評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼惠奸,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼梅誓!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起佛南,我...
    開封第一講書人閱讀 39,008評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤梗掰,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后嗅回,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體及穗,經(jīng)...
    沈念sama閱讀 45,443評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,649評(píng)論 3 334
  • 正文 我和宋清朗相戀三年绵载,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了埂陆。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,795評(píng)論 1 347
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡娃豹,死狀恐怖焚虱,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情懂版,我是刑警寧澤鹃栽,帶...
    沈念sama閱讀 35,501評(píng)論 5 345
  • 正文 年R本政府宣布,位于F島的核電站躯畴,受9級(jí)特大地震影響民鼓,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜私股,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,119評(píng)論 3 328
  • 文/蒙蒙 一摹察、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧倡鲸,春花似錦、人聲如沸黄娘。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,731評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至优床,卻和暖如春劝赔,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背胆敞。 一陣腳步聲響...
    開封第一講書人閱讀 32,865評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工着帽, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人移层。 一個(gè)月前我還...
    沈念sama閱讀 47,899評(píng)論 2 370
  • 正文 我出身青樓仍翰,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親观话。 傳聞我的和親對(duì)象是個(gè)殘疾皇子予借,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,724評(píng)論 2 354