乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      Thrift使用指南 | 董的博客

       royy 2012-05-13

      1. 內(nèi)容概要

      本文檔比較全面的介紹了thrift(關(guān)于thrift框架的介紹,參考我這篇文章:Thrift框架介紹)語法,代碼生成結(jié)構(gòu)和應(yīng)用經(jīng)驗(yàn)。本文主要講述的對(duì)象是thrift文件,并未涉及其client和server的編寫方法(關(guān)于client和server的編寫方法,可參考我這篇文章:使用Thrift RPC編寫程序)。

      本文檔大部分內(nèi)容翻譯自文章:Thrift:The missing Guide

      2. 語法參考

      2.1 Types

      Thrift類型系統(tǒng)包括預(yù)定義基本類型,用戶自定義結(jié)構(gòu)體,容器類型,異常和服務(wù)定義

      (1) 基本類型

      bool:布爾類型(true or value),占一個(gè)字節(jié)
      
      byte:有符號(hào)字節(jié)
      
      i16:16位有符號(hào)整型
      
      i32:32位有符號(hào)整型
      
      i64:64位有符號(hào)整型
      
      double:64位浮點(diǎn)數(shù)
      
      string:未知編碼或者二進(jìn)制的字符串
      

      注意,thrift不支持無符號(hào)整型,因?yàn)楹芏嗄繕?biāo)語言不存在無符號(hào)整型(如java)。

      (2) 容器類型

      Thrift容器與類型密切相關(guān),它與當(dāng)前流行編程語言提供的容器類型相對(duì)應(yīng),采用java泛型風(fēng)格表示的。Thrift提供了3種容器類型:

      List<t1>:一系列t1類型的元素組成的有序表,元素可以重復(fù)

      Set<t1>:一系列t1類型的元素組成的無序表,元素唯一

      Map<t1,t2>:key/value對(duì)(key的類型是t1且key唯一,value類型是t2)。

      容器中的元素類型可以是除了service意外的任何合法thrift類型(包括結(jié)構(gòu)體和異常)。

      (3)  結(jié)構(gòu)體和異常

      Thrift結(jié)構(gòu)體在概念上同C語言結(jié)構(gòu)體類型—-一種將相關(guān)屬性聚集(封裝)在一起的方式。在面向?qū)ο笳Z言中,thrift結(jié)構(gòu)體被轉(zhuǎn)換成類。

      異常在語法和功能上類似于結(jié)構(gòu)體,只不過異常使用關(guān)鍵字exception而不是struct關(guān)鍵字聲明。但它在語義上不同于結(jié)構(gòu)體—當(dāng)定義一個(gè)RPC服務(wù)時(shí),開發(fā)者可能需要聲明一個(gè)遠(yuǎn)程方法拋出一個(gè)異常。

      結(jié)構(gòu)體和異常的聲明將在下一節(jié)介紹。

      (4)  服務(wù)

      服務(wù)的定義方法在語法上等同于面向?qū)ο笳Z言中定義接口。Thrift編譯器會(huì)產(chǎn)生實(shí)現(xiàn)這些接口的client和server樁。具體參見下一節(jié)。

      (5)  類型定義

      Thrift支持C/C++風(fēng)格的typedef:

      typedef i32 MyInteger   \\a
      
      typedef Tweet ReTweet  \\b
      

      說明:

      a.  末尾沒有逗號(hào)

      b.   struct可以使用typedef

      2.2   枚舉類型

      可以像C/C++那樣定義枚舉類型,如:

      enum TweetType {
      
      TWEET,       //a
      
      RETWEET = 2, //b
      
      DM = 0xa,  //c
      
      REPLY
      
      }        //d
      
      struct Tweet {
      
      1: required i32 userId;
      
      2: required string userName;
      
      3: required string text;
      
      4: optional Location loc;
      
      5: optional TweetType tweetType = TweetType.TWEET // e
      
      16: optional string language = "english"
      
      }
      

      說明:

      a.  編譯器默認(rèn)從0開始賦值

      b.  可以賦予某個(gè)常量某個(gè)整數(shù)

      c.  允許常量是十六進(jìn)制整數(shù)

      d.  末尾沒有逗號(hào)

      e.  給常量賦缺省值時(shí),使用常量的全稱

      注意,不同于protocol buffer,thrift不支持枚舉類嵌套,枚舉常量必須是32位的正整數(shù)

      2.3   注釋

      Thrfit支持shell注釋風(fēng)格,C/C++語言中單行或者多行注釋風(fēng)格

      # This is a valid comment.
      
      /*
      
      * This is a multi-line comment.
      
      * Just like in C.
      
      */
      
      // C++/Java style single-line comments work just as well.
      

      2.4   命名空間

      Thrift中的命名空間同C++中的namespace和java中的package類似,它們均提供了一種組織(隔離)代碼的方式。因?yàn)槊糠N語言均有自己的命名空間定義方式(如python中有module),thrift允許開發(fā)者針對(duì)特定語言定義namespace:

      namespace cpp com.example.project  // a
      
      namespace java com.example.project // b
      

      說明:

      a.  轉(zhuǎn)化成namespace com { namespace example { namespace project {

      b.  轉(zhuǎn)換成package com.example.project

      2.5   文件包含

      Thrift允許thrift文件包含,用戶需要使用thrift文件名作為前綴訪問被包含的對(duì)象,如:

      include "tweet.thrift"           // a
      
      ...
      
      struct TweetSearchResult {
      
      1: list<tweet.Tweet> tweets; // b
      
      }
      

      說明:

      a.  thrift文件名要用雙引號(hào)包含,末尾沒有逗號(hào)或者分號(hào)

      b.  注意tweet前綴

      2.6   常量

      Thrift允許用戶定義常量,復(fù)雜的類型和結(jié)構(gòu)體可使用JSON形式表示。

      const i32 INT_CONST = 1234;    // a
      
      const map<string,string> MAP_CONST = {"hello": "world", "goodnight": "moon"}
      

      說明:

      a.  分號(hào)是可選的,可有可無;支持十六進(jìn)制賦值。

      2.7   定義結(jié)構(gòu)體

      結(jié)構(gòu)體由一系列域組成,每個(gè)域有唯一整數(shù)標(biāo)識(shí)符,類型,名字和可選的缺省參數(shù)組成。如:

      struct Tweet {
      
      1: required i32 userId;                  // a
      
      2: required string userName;             // b
      
      3: required string text;
      
      4: optional Location loc;                // c
      
      16: optional string language = "english" // d
      
      }
      
      struct Location {                            // e
      
      1: required double latitude;
      
      2: required double longitude;
      
      }
      

      說明:

      a.  每個(gè)域有一個(gè)唯一的,正整數(shù)標(biāo)識(shí)符

      b.  每個(gè)域可以標(biāo)識(shí)為required或者optional(也可以不注明)

      c.  結(jié)構(gòu)體可以包含其他結(jié)構(gòu)體

      d.  域可以有缺省值

      e.  一個(gè)thrift中可定義多個(gè)結(jié)構(gòu)體,并存在引用關(guān)系

      規(guī)范的struct定義中的每個(gè)域均會(huì)使用required或者optional關(guān)鍵字進(jìn)行標(biāo)識(shí)。如果required標(biāo)識(shí)的域沒有賦值,thrift將給予提示。如果optional標(biāo)識(shí)的域沒有賦值,該域?qū)⒉粫?huì)被序列化傳輸。如果某個(gè)optional標(biāo)識(shí)域有缺省值而用戶沒有重新賦值,則該域的值一直為缺省值。

      與service不同,結(jié)構(gòu)體不支持繼承,即,一個(gè)結(jié)構(gòu)體不能繼承另一個(gè)結(jié)構(gòu)體。

      2.8   定義服務(wù)

      在流行的序列化/反序列化框架(如protocol buffer)中,thrift是少有的提供多語言間RPC服務(wù)的框架。

      Thrift編譯器會(huì)根據(jù)選擇的目標(biāo)語言為server產(chǎn)生服務(wù)接口代碼,為client產(chǎn)生樁代碼。

      //“Twitter”與“{”之間需要有空格?。?!
      service Twitter {
      
      // 方法定義方式類似于C語言中的方式,它有一個(gè)返回值,一系列參數(shù)和可選的異常
      
      // 列表. 注意,參數(shù)列表和異常列表定義方式與結(jié)構(gòu)體中域定義方式一致.
      
      void ping(),                                    // a
      
      bool postTweet(1:Tweet tweet);                  // b
      
      TweetSearchResult searchTweets(1:string query); // c
      
      // ”oneway”標(biāo)識(shí)符表示client發(fā)出請(qǐng)求后不必等待回復(fù)(非阻塞)直接進(jìn)行下面的操作,
      
      // ”oneway”方法的返回值必須是void
      
      oneway void zip()                               // d
      
      }
      

      說明:

      a. 函數(shù)定義可以使用逗號(hào)或者分號(hào)標(biāo)識(shí)結(jié)束

      b. 參數(shù)可以是基本類型或者結(jié)構(gòu)體,參數(shù)是只讀的(const),不可以作為返回值?。?!

      c. 返回值可以是基本類型或者結(jié)構(gòu)體

      d. 返回值可以是void

      注意,函數(shù)中參數(shù)列表的定義方式與struct完全一樣

      Service支持繼承,一個(gè)service可使用extends關(guān)鍵字繼承另一個(gè)service

      3.  產(chǎn)生代碼

      本節(jié)介紹thrift產(chǎn)生各種目標(biāo)語言代碼的方式。本節(jié)從幾個(gè)基本概念開始,逐步引導(dǎo)開發(fā)者了解產(chǎn)生的代碼是怎么樣組織的,進(jìn)而幫助開發(fā)者更快地明白thrift的使用方法。

      概念

      Thrift的網(wǎng)絡(luò)棧如下所示:

      3.1   Transport

      Transport層提供了一個(gè)簡(jiǎn)單的網(wǎng)絡(luò)讀寫抽象層。這使得thrift底層的transport從系統(tǒng)其它部分(如:序列化/反序列化)解耦。以下是一些Transport接口提供的方法:

      open
      
      close
      
      read
      
      write
      
      flush
      

      除了以上幾個(gè)接口,Thrift使用ServerTransport接口接受或者創(chuàng)建原始transport對(duì)象。正如名字暗示的那樣,ServerTransport用在server端,為到來的連接創(chuàng)建Transport對(duì)象。

      open
      
      listen
      
      accept
      
      close
      

      3.2   Protocol

      Protocol抽象層定義了一種將內(nèi)存中數(shù)據(jù)結(jié)構(gòu)映射成可傳輸格式的機(jī)制。換句話說,Protocol定義了datatype怎樣使用底層的Transport對(duì)自己進(jìn)行編解碼。因此,Protocol的實(shí)現(xiàn)要給出編碼機(jī)制并負(fù)責(zé)對(duì)數(shù)據(jù)進(jìn)行序列化。

      Protocol接口的定義如下:

      writeMessageBegin(name, type, seq)
      
      writeMessageEnd()
      
      writeStructBegin(name)
      
      writeStructEnd()
      
      writeFieldBegin(name, type, id)
      
      writeFieldEnd()
      
      writeFieldStop()
      
      writeMapBegin(ktype, vtype, size)
      
      writeMapEnd()
      
      writeListBegin(etype, size)
      
      writeListEnd()
      
      writeSetBegin(etype, size)
      
      writeSetEnd()
      
      writeBool(bool)
      
      writeByte(byte)
      
      writeI16(i16)
      
      writeI32(i32)
      
      writeI64(i64)
      
      writeDouble(double)
      
      writeString(string)
      
      name, type, seq = readMessageBegin()
      
      readMessageEnd()
      
      name = readStructBegin()
      
      readStructEnd()
      
      name, type, id = readFieldBegin()
      
      readFieldEnd()
      
      k, v, size = readMapBegin()
      
      readMapEnd()
      
      etype, size = readListBegin()
      
      readListEnd()
      
      etype, size = readSetBegin()
      
      readSetEnd()
      
      bool = readBool()
      
      byte = readByte()
      
      i16 = readI16()
      
      i32 = readI32()
      
      i64 = readI64()
      
      double = readDouble()
      
      string = readString()
      

      下面是一些對(duì)大部分thrift支持的語言均可用的protocol:

      (1)     binary:簡(jiǎn)單的二進(jìn)制編碼

      (2)     Compact:具體見THRIFT-11

      (3)     Json

      3.3   Processor

      Processor封裝了從輸入數(shù)據(jù)流中讀數(shù)據(jù)和向數(shù)據(jù)數(shù)據(jù)流中寫數(shù)據(jù)的操作。讀寫數(shù)據(jù)流用Protocol對(duì)象表示。Processor的結(jié)構(gòu)體非常簡(jiǎn)單:

      interface TProcessor {
      
      bool process(TProtocol in, TProtocol out) throws TException
      
      }
      

      與服務(wù)相關(guān)的processor實(shí)現(xiàn)由編譯器產(chǎn)生。Processor主要工作流程如下:從連接中讀取數(shù)據(jù)(使用輸入protocol),將處理授權(quán)給handler(由用戶實(shí)現(xiàn)),最后將結(jié)果寫到連接上(使用輸出protocol)。

      3.4   Server

      Server將以上所有特性集成在一起:

      (1)  創(chuàng)建一個(gè)transport對(duì)象

      (2)  為transport對(duì)象創(chuàng)建輸入輸出protocol

      (3)  基于輸入輸出protocol創(chuàng)建processor

      (4)  等待連接請(qǐng)求并將之交給processor處理

      3.5   應(yīng)用舉例

      下面,我們討論thrift文件產(chǎn)生的特定語言代碼。下面給出thrift文件描述:

      namespace cpp thrift.example
      
      namespace java thrift.example
      
      enum TweetType {
      
      TWEET,
      
      RETWEET = 2,
      
      DM = 0xa,
      
      REPLY
      
      }
      
      struct Location {
      
      1: required double latitude;
      
      2: required double longitude;
      
      }
      
      struct Tweet {
      
      1: required i32 userId;
      
      2: required string userName;
      
      3: required string text;
      
      4: optional Location loc;
      
      5: optional TweetType tweetType = TweetType.TWEET;
      
      16: optional string language = "english";
      
      }
      
      typedef list<Tweet> TweetList
      
      struct TweetSearchResult {
      
      1: TweetList tweets;
      
      }
      
      const i32 MAX_RESULTS = 100;
      
      service Twitter {
      
      void ping(),
      
      bool postTweet(1:Tweet tweet);
      
      TweetSearchResult searchTweets(1:string query);
      
      oneway void zip()
      
      }
      

      (1) Java語言

      (a)  產(chǎn)生的文件

      一個(gè)單獨(dú)的文件(Constants.java)包含所有的常量定義。

      每個(gè)結(jié)構(gòu)體,枚舉或者服務(wù)各占一個(gè)文件

      $ tree gen-java

      `– thrift

      `– example

      |– Constants.java

      |– Location.java

      |– Tweet.java

      |– TweetSearchResult.java

      |– TweetType.java

      `– Twitter.java

      (b)  類型

      thrift將各種基本類型和容器類型映射成java類型:

      bool: boolean
      
      byte: byte
      
      i16: short
      
      i32: int
      
      i64: long
      
      double: double
      
      string: String
      
      list<t1>: List<t1>
      
      set<t1>: Set<t1>
      
      map<t1,t2>: Map<t1, t2>
      

      (c)  typedef

      Java不支持typedef,它只使用原始類型,如,在上面的例子中,產(chǎn)生的代碼中,TweetSearchResult會(huì)被還原成list<Tweet> tweets

      (d)  Enum

      Thrift直接將枚舉類型映射成java的枚舉類型。用戶可以使用geValue方法獲取枚舉常量的值。此外,編譯器會(huì)產(chǎn)生一個(gè)findByValue方法獲取枚舉對(duì)應(yīng)的數(shù)值。

      (e)  常量

      Thrift把所有的常量放在一個(gè)叫Constants的public類中,每個(gè)常量修飾符是public static final。

      (2)  C++語言

      (a)  產(chǎn)生的文件

      所有變量均存放在一個(gè).cpp/.h文件對(duì)中

      所有的類型定義(枚舉或者結(jié)構(gòu)體)存放到另一個(gè).cpp/.h文件對(duì)中

      每一個(gè)service有自己的.cpp/.h文件

      $ tree gen-cpp

      |– example_constants.cpp

      |– example_constants.h

      |– example_types.cpp

      |– example_types.h

      |– Twitter.cpp

      |– Twitter.h

      `– Twitter_server.skeleton.cpp

      其他語言

      Python,Ruby,javascript等

      4.  實(shí)踐經(jīng)驗(yàn)

      thrift文件內(nèi)容可能會(huì)隨著時(shí)間變化的。如果已經(jīng)存在的消息類型不再符合設(shè)計(jì)要求,比如,新的設(shè)計(jì)要在message格式中添加一個(gè)額外字段,但你仍想使用以前的thrift文件產(chǎn)生的處理代碼。如果想要達(dá)到這個(gè)目的,只需:

      (1)  不要修改已存在域的整數(shù)編號(hào)

      (2)  新添加的域必須是optional的,以便格式兼容。對(duì)于一些語言,如果要為optional的字段賦值,需要特殊處理,比如對(duì)于C++語言,要為

      struct Example{
      
      1 : i32 id,
      
      2 : string name,
      
      3 : optional age,
      
      }
      

      中的optional字段age賦值,需要將它的__isset值設(shè)為true,這樣才能序列化并傳輸或者存儲(chǔ)(不然optional字段被認(rèn)為不存在,不會(huì)被傳輸或者存儲(chǔ)),

      如:

      Example example;
      
      ......
      
      example.age=10,
      
      example.__isset.age = true; //__isset是每個(gè)thrift對(duì)象的自帶的public成員,來指定optional字段是否啟用并賦值。
      
      ......
      

      (3)  非required域可以刪除,前提是它的整數(shù)編號(hào)不會(huì)被其他域使用。對(duì)于刪除的字段,名字前面可添加“OBSOLETE_”以防止其他字段使用它的整數(shù)編號(hào)。

      (4) thrift文件應(yīng)該是unix格式的(windows下的換行符與unix不同,可能會(huì)導(dǎo)致你的程序編譯不過),如果是在window下編寫的,可使用dos2unix轉(zhuǎn)化為unix格式。

      (5)  貌似當(dāng)前的thrift版本(0.6.1)不支持常量表達(dá)式的定義(如 const i32 DAY = 24 * 60 * 60),這可能是考慮到不同語言,運(yùn)算符不盡相同。

        本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
        轉(zhuǎn)藏 分享 獻(xiàn)花(0

        0條評(píng)論

        發(fā)表

        請(qǐng)遵守用戶 評(píng)論公約

        類似文章 更多