AVRO

Avro([?vr?])是Hadoop的一個(gè)子項(xiàng)目,由Hadoop的創(chuàng)始人Doug Cutting(也是Lucene涣狗,Nutch等項(xiàng)目的創(chuàng)始人)牽頭開發(fā)。Avro是一個(gè)數(shù)據(jù)序列化系統(tǒng)舒憾,設(shè)計(jì)用于支持大批量數(shù)據(jù)交換的應(yīng)用镀钓。它的主要特點(diǎn)有:支持二進(jìn)制序列化方式,可以便捷镀迂,快速地處理大量數(shù)據(jù)丁溅;動(dòng)態(tài)語(yǔ)言友好,Avro提供的機(jī)制使動(dòng)態(tài)語(yǔ)言可以方便地處理Avro數(shù)據(jù)探遵。

一窟赏、數(shù)據(jù)序列化/反序列化(data serialization/deserialization)

Avro支持兩種序列化編碼方式:二進(jìn)制編碼和JSON編碼。使用二進(jìn)制編碼會(huì)高效序列化箱季,并且序列化后得到的結(jié)果會(huì)比較醒那睢;而JSON一般用于調(diào)試系統(tǒng)或是基于WEB的應(yīng)用藏雏。對(duì)Avro數(shù)據(jù)序列化/反序列化時(shí)都需要對(duì)模式以深度優(yōu)先(Depth-First)拷况,從左到右(Left-to-Right)的遍歷順序來(lái)執(zhí)行。
Avro依賴模式(Schema)來(lái)實(shí)現(xiàn)數(shù)據(jù)結(jié)構(gòu)定義掘殴∽荩可以把模式理解為Java的類,它定義每個(gè)實(shí)例的結(jié)構(gòu)奏寨,可以包含哪些屬性起意。可以根據(jù)類來(lái)產(chǎn)生任意多個(gè)實(shí)例對(duì)象服爷。對(duì)實(shí)例序列化操作時(shí)必須需要知道它的基本結(jié)構(gòu)杜恰,也就需要參考類的信息。這里仍源,根據(jù)模式產(chǎn)生的Avro對(duì)象類似于類的實(shí)例對(duì)象心褐。每次序列化/反序列化時(shí)都需要知道模式的具體結(jié)構(gòu)。所以笼踩,在Avro可用的一些場(chǎng)景下逗爹,如文件存儲(chǔ)或是網(wǎng)絡(luò)通信,都需要模式與數(shù)據(jù)同時(shí)存在。Avro數(shù)據(jù)以模式來(lái)讀和寫(文件或是網(wǎng)絡(luò))掘而,并且寫入的數(shù)據(jù)都不需要加入其它標(biāo)識(shí)挟冠,這樣序列化時(shí)速度快且結(jié)果內(nèi)容少。由于程序可以直接根據(jù)模式來(lái)處理數(shù)據(jù)袍睡,所以Avro更適合于腳本語(yǔ)言的發(fā)揮知染。

  1. 需要的Jar包依賴
    avro-1.7.3.jar,avro-tools-1.7.3.jar斑胜,jackson-core-asl-1.9.3.jar控淡,jackson-mapper-asl-1.9.3.jar

  2. 定義模式(Schema)
    在avro中,它是用Json格式來(lái)定義模式的止潘。模式可以由基礎(chǔ)類型(null, boolean, int, long, float, double, bytes, and string)和復(fù)合類型(record, enum, array, map, union, and fixed)的數(shù)據(jù)組成掺炭。這里定義了一個(gè)簡(jiǎn)單的模式user.avsc:

{
    "namespace": "com.zq.avro",
    "type": "record",
    "name": "User",
    "fields": [
        {"name": "name", "type": "string"},
        {"name": "favorite_number", "type": ["int", "null"]},
        {"name": "favorite_color", "type": ["string", "null"]}
    ]
}

上面的模式是定義了一個(gè)用戶的記錄,在模式定義中凭戴,必須包含它的類型("type": "record")涧狮、一個(gè)名字("name": "User")以及fields。在本例中fields包括了name, favorite_number和favorite_color么夫,上面的模式我們還定義了一個(gè)命名空間 ("namespace": "com.zq.avro"),namespace可以名字一起使用者冤,從而組成模式的全名(本例為com.zq.avro.User)。

  1. 編譯模式(compile schema)
    Avro可以允許我們根據(jù)模式的定義而生成相應(yīng)的類魏割,一旦我們定義好相關(guān)的類譬嚣,程序中就不需要直接使用模式了〕可以用avro-tools jar包根據(jù)user.avsc生成User.java拜银,語(yǔ)法如下:
java -jar avro-tools-1.7.4.jar compile schema . [注意這里有第三個(gè)參數(shù)"."]

命令執(zhí)行后會(huì)在當(dāng)前目錄根據(jù)設(shè)定的包結(jié)構(gòu)生成一個(gè)User.java類,然后就可以將定義的User對(duì)象用avro將它序列化存放到本地文件中遭垛,再將其反序列化尼桶。

  1. 編寫Java代碼
public static void main(String[] args) throws Exception {
        User user1 = new User();
        user1.setName("Arway");
        user1.setFavoriteNumber(3);
        user1.setFavoriteColor("green");
        User user2 = new User("Ben", 7, "red");
        // construct with builder
        User user3 = User.newBuilder().setName("Charlie").setFavoriteColor("blue").setFavoriteNumber(100).build();
        // Serialize user1, user2 and user3 to disk
        File file = new File("C:\\Users\\kimibob\\Desktop\\users.avro");
        DatumWriter<User> userDatumWriter = new SpecificDatumWriter<User>(User.class);
        DataFileWriter<User> dataFileWriter = new DataFileWriter<User>(userDatumWriter);
        try {
            dataFileWriter.create(user1.getSchema(), file);
            dataFileWriter.append(user1);
            dataFileWriter.append(user2);
            dataFileWriter.append(user3);
            dataFileWriter.close();
        } catch (IOException e) {
        }
        // Deserialize Users from dist
        DatumReader<User> userDatumReader = new SpecificDatumReader<User>(User.class);
        DataFileReader<User> dataFileReader = null;
        try {
            dataFileReader = new DataFileReader<User>(file, userDatumReader);
        } catch (IOException e) {
        }
        User user = null;
        try {
            while (dataFileReader.hasNext()) {
                // Reuse user object by passing it to next(). This saves
                // us from allocating and garbage collecting many objects for
                // files with many items.
                user = dataFileReader.next(user);
                System.out.println(user);
            }
        } catch (IOException e) {
        }
    }

運(yùn)行完這段代碼之后,將會(huì)在磁盤產(chǎn)生users.avro文件锯仪,里面是用avro序列化user的二進(jìn)制數(shù)據(jù)泵督,再對(duì)其進(jìn)行反序列化,在控制臺(tái)輸出文本json格式的數(shù)據(jù)庶喜。

{"name": "Arway", "favorite_number": 3, "favorite_color": "green"}
{"name": "Ben", "favorite_number": 7, "favorite_color": "red"}
{"name": "Charlie", "favorite_number": 100, "favorite_color": "blue"}

對(duì)比可以看出序列化后的avro格式文件大小遠(yuǎn)小于文本格式小腊,有利于節(jié)省網(wǎng)絡(luò)傳輸?shù)拈_銷。

二久窟、Avro RPC框架

  • RPC邏輯上分為二層秩冈,一是傳輸層,負(fù)責(zé)網(wǎng)絡(luò)通信斥扛;二是協(xié)議層入问,將數(shù)據(jù)按照一定協(xié)議格式打包和解包
  • 從序列化方式來(lái)看,Apache Thrift 和Google的Protocol Buffers和Avro應(yīng)該是屬于同一個(gè)級(jí)別的框架,都能跨語(yǔ)言芬失,性能優(yōu)秀楣黍,數(shù)據(jù)精簡(jiǎn),但是Avro的動(dòng)態(tài)模式(不用生成代碼棱烂,而且性能很好)這個(gè)特點(diǎn)讓人非常喜歡租漂,比較適合RPC的數(shù)據(jù)交換。
  • Avro RPC 是一個(gè)支持跨語(yǔ)言實(shí)現(xiàn)的RPC服務(wù)框架垢啼。非常輕量級(jí)窜锯,實(shí)現(xiàn)簡(jiǎn)潔,使用方便芭析,同時(shí)支持使用者進(jìn)行二次開發(fā),邏輯上該框架分為兩層:
    1.網(wǎng)絡(luò)傳輸層使用Netty的Nio實(shí)現(xiàn)吞瞪。
    2.協(xié)議層可擴(kuò)展馁启,目前支持的數(shù)據(jù)序列化方式有Avro, Protocol Buffers, Json, Hessian,Java序列化。 使用者可以注冊(cè)自己的協(xié)議格式及序列化方式芍秆。

上面是將Avro對(duì)象序列化到文件的操作惯疙。與之相應(yīng)的,Avro也被作為一種RPC框架來(lái)使用妖啥∶沟撸客戶端希望同服務(wù)器端交互時(shí),就需要交換雙方通信的協(xié)議荆虱,它類似于模式蒿偎,需要雙方來(lái)定義,在Avro中被稱為消息(Message)怀读。通信雙方都必須保持這種協(xié)議诉位,以便于解析從對(duì)方發(fā)送過(guò)來(lái)的數(shù)據(jù),這也就是傳說(shuō)中的握手(handshake)階段菜枷。

Avro RPC開發(fā)
  1. 需要的Jar包依賴
    avro-1.7.3.jar苍糠, avro-ipc-1.7.3.jar, netty-3.5.12.Final.jar啤誊, slf4j-api-1.6.1.jar
  2. 定義協(xié)議模式(protocol Schema)
{"namespace": "com.zq.avro",
 "protocol": "Mail",

 "types": [
     {"name": "Message", "type": "record",
      "fields": [
          {"name": "to",   "type": "string"},
          {"name": "from", "type": "string"},
          {"name": "body", "type": "string"}
      ]
     }
 ],
 "messages": {
     "send": {
         "request": [{"name": "message", "type": "Message"}],
         "response": "string"
     }
 }
}
  1. 編譯模式(compile schema)
java -jar avro-tools-1.7.3.jar compile protocol mail.avpr . [注意這里有第三個(gè)參數(shù)"."]

命令執(zhí)行后會(huì)在當(dāng)前目錄根據(jù)設(shè)定的包結(jié)構(gòu)生成一個(gè)Mail接口和一個(gè)Message類岳瞭。

  1. 編寫Java代碼
    AvroServer類:
class MailImpl implements Mail {

    @Override
    public CharSequence send(Message message) throws AvroRemoteException {
        System.out.println("Message Received:" + message);
        return new Utf8("Received your message: " + message.getFrom().toString() + " with body "
                + message.getBody().toString());
        }
}
public class AvroServer {

    private static Server server;

    public static void main(String[] args) throws Exception {

        System.out.println("Starting server");
        startServer();
        Thread.sleep(1000);
        System.out.println("Server started");
        Thread.sleep(60 * 1000);
        server.close();
    }

    private static void startServer() throws IOException {
        server = new NettyServer(new SpecificResponder(Mail.class, new MailImpl()), new InetSocketAddress(65111));
    }
}

AvroClient類:

public class AvroClient {
    public static void main(String[] args) throws Exception {
        NettyTransceiver client = new NettyTransceiver(new InetSocketAddress(65111));
        /// 獲取Mail接口的proxy實(shí)現(xiàn)
        Mail proxy = SpecificRequestor.getClient(Mail.class, client);
        System.out.println("Client of Mail Proxy is built");

        // fill in the Message record and send it
        args = new String[] { "to:Tom", "from:Jack", "body:How are you" };
        Message message = new Message();
        message.setTo(new Utf8(args[0]));
        message.setFrom(new Utf8(args[1]));
        message.setBody(new Utf8(args[2]));
        System.out.println("RPC call with message:  " + message.toString());

        /// 底層給服務(wù)器發(fā)送send方法調(diào)用
        System.out.println("Result: " + proxy.send(message));

        // cleanup
        client.close();
    }
}

擴(kuò)展:

  • Netty是什么?
    本質(zhì):JBoss做的一個(gè)Jar包
    目的:快速開發(fā)高性能蚊锹、高可靠性的網(wǎng)絡(luò)服務(wù)器和客戶端程序
    優(yōu)點(diǎn):提供異步的瞳筏、事件驅(qū)動(dòng)的網(wǎng)絡(luò)應(yīng)用程序框架和工具
    通俗的說(shuō):Netty是一個(gè)NIO的框架,可以用于開發(fā)分布式的Java程序
  • 如果沒(méi)有Netty枫耳?
    遠(yuǎn)古:java.net + java.io
    近代:java.nio
    其他:Mina乏矾,Grizzly
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子钻心,更是在濱河造成了極大的恐慌凄硼,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,817評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件捷沸,死亡現(xiàn)場(chǎng)離奇詭異摊沉,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)痒给,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,329評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門说墨,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人苍柏,你說(shuō)我怎么就攤上這事尼斧。” “怎么了试吁?”我有些...
    開封第一講書人閱讀 157,354評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵棺棵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我熄捍,道長(zhǎng)烛恤,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,498評(píng)論 1 284
  • 正文 為了忘掉前任余耽,我火速辦了婚禮缚柏,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘碟贾。我一直安慰自己币喧,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,600評(píng)論 6 386
  • 文/花漫 我一把揭開白布缕陕。 她就那樣靜靜地躺著粱锐,像睡著了一般。 火紅的嫁衣襯著肌膚如雪扛邑。 梳的紋絲不亂的頭發(fā)上怜浅,一...
    開封第一講書人閱讀 49,829評(píng)論 1 290
  • 那天,我揣著相機(jī)與錄音蔬崩,去河邊找鬼恶座。 笑死,一個(gè)胖子當(dāng)著我的面吹牛沥阳,可吹牛的內(nèi)容都是我干的跨琳。 我是一名探鬼主播,決...
    沈念sama閱讀 38,979評(píng)論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼桐罕,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼桂敛!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起溅潜,我...
    開封第一講書人閱讀 37,722評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤术唬,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后滚澜,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體粗仓,經(jīng)...
    沈念sama閱讀 44,189評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,519評(píng)論 2 327
  • 正文 我和宋清朗相戀三年设捐,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了借浊。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,654評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡萝招,死狀恐怖蚂斤,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情即寒,我是刑警寧澤橡淆,帶...
    沈念sama閱讀 34,329評(píng)論 4 330
  • 正文 年R本政府宣布,位于F島的核電站母赵,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏具滴。R本人自食惡果不足惜凹嘲,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,940評(píng)論 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望构韵。 院中可真熱鬧周蹭,春花似錦、人聲如沸疲恢。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,762評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)显拳。三九已至棚愤,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間杂数,已是汗流浹背宛畦。 一陣腳步聲響...
    開封第一講書人閱讀 31,993評(píng)論 1 266
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留揍移,地道東北人次和。 一個(gè)月前我還...
    沈念sama閱讀 46,382評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像那伐,于是被迫代替她去往敵國(guó)和親踏施。 傳聞我的和親對(duì)象是個(gè)殘疾皇子石蔗,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,543評(píng)論 2 349

推薦閱讀更多精彩內(nèi)容