HBase 客戶端類型 (一)

HBase 自帶了很多用於各種編程語言客戶端。

 

1. 介紹 (Introduction)
----------------------------
從目前非常流行的語言和環境可以訪問 HBase。可以直接使用客戶端 API, 或者通過一些中間代理訪問,將用戶請求翻譯成 API 調用。這些代理將原生的
Java API 包裝成其它協議的 API,這樣客戶端就可以使用這些對外提供的 API 以任意語言來編寫。通常來說,外部 API 實現爲一個專用的基於 Java 的
服務器,可以在內部使用 HBase 提供的 Table 客戶端 API. 這樣簡化了網關服務器(gateway servers)的實現和維護。

另一方面,有很多工具儘量隱藏 HBase 和它所提供的 API, 用戶可與特定的接口對話,或者面向一組庫來開發來形成訪問層,例如,提供一個數據訪問對象(
data access objects, DAOs)的持久層.

 


1.1 網關 (Gateways)
-----------------------------------------------------------------------------------------------------------------------------------------
回到網關的方法,網關與客戶端之間是由當前可用的選擇和遠程客戶端的要求驅動的。其中最常用的就是 REST(Representational State Transfer,
即表述性狀態傳遞),它是基於現有的 web 技術。實際的傳輸協議是典型的 HTTP 協議,web 應用的標準協議。由於協議層負責傳輸可互操作格式的數據,這
使 REST 稱爲異構系統之間傳輸數據的理想選擇。

REST 自定義了語義,這樣,協議就可以用於以普通的方式定位遠程服務的資源。不用改變協議,REST 可以兼容現有的技術,例如,web server 以及 proxy.
資源作爲請求 URI 的一部分唯一指定,與此相反,例如,基於 SOAP 的服務,要定義一個新協議來適應標準。

然而,REST 和 SOAP 都面臨冗長的協議等級,用於客戶端和服務器端通信的人類可讀文本,可以是純文本或者基於 XML。對網絡間傳輸的數據進行透明壓縮
可以在一定程度上緩解這個問題。

作爲一個結果,擁有大量服務器的企業,大量的帶寬佔用和許多相互隔離的服務,覺得需要降低帶寬開銷並實現自己的 RPC 層。Google 就是其中之一,它們
實現了 Protocol Buffers。由於這個實現起初沒有發佈,Facebook 開發了自己的版本,叫做 Thrift.

這些項目都有類似的特性集,不同之處在於它們所支持的語言數量。Protocol Buffers 與 Thrift 比較關鍵不同的是,Protocol Buffers 沒有自己的 RPC
棧(RPC stack), 而是生成 RPC 定義,可以與其它 RPC 庫使用。

HBase 爲 REST 和 Thrift 提供了輔助服務器,它們實現爲獨立網關服務器(standalone gateway servers), 可以運行在獨立或專用的服務器上。由於 Thrift
有自己的 RPC 實現,網關服務器只是爲它們提供了簡單的封裝。對於 REST, HBase 有自己的實現,提供訪問存儲的數據。

    NOTE:
    -------------------------------------------------------------------------------------------------------------------------------------
    HBase 提供的 RESTServer 實際上支持 Protocol Buffers,沒有實現一個單獨的 RPC 服務器,而是利用了 HTTP 的 Accept 頭來發送和接收在
    Protocol Buffers 中編碼的數據。
    
沒有人建議網關服務器如何部署,可以將它與其它服務器共存運行,也可以運行在專用的集羣上。

另一種方法時直接將它們允許在客戶端節點上。例如,有一個 web 服務器,通過 PHP 構建網頁,將網關進程運行在這臺服務器上是有利的。這樣,客戶端與
網關的通信是在本地,而網關與 HBase 之間的 RPC 通信是原生協議。

選擇一種網關類型不是一個簡單的任務,這取決於用戶的應用場景:


    REST Use Case
    -------------------------------------------------------------------------------------------------------------------------------------
    REST 支持現有的基於 web 的體系,它能夠完美地融合反向代理和其它緩存技術。並行運行多個 REST 服務器可以分攤它們之間的負載。例如,在每個
    運行應用服務器的機器上運行 REST 服務,構建一個 single-app-to-server 關係。


    Thrift/Avro Use Case
    -------------------------------------------------------------------------------------------------------------------------------------
    當需要在吞吐量上獲取最好的性能時,使用緊湊的二進制協議。可以運行較少的服務器,例如,每個 region 服務器上運行一個 Thrift/Avro 服務器,
    構成 many-apps-to-server 關係。


    NOTE:
    -------------------------------------------------------------------------------------------------------------------------------------
    HBase 也含有一個 Avro 的 gateway server, 但由於較少的關注和支持,已在 HBase 0.96 之後的版本中放棄了。

 


1.2 框架 (Frameworks)
-----------------------------------------------------------------------------------------------------------------------------------------
軟件開發的一個長期的趨勢是模塊化和解耦特定工作單元。可以將其稱爲職責分離(separation of responsibilities)或其它類似的名稱,但它們的目標是
一致的:一次性構建通用的軟件片段,而不是一遍一遍地重複發明輪子。很多編程語言都有模塊的概念,在 Java 中是 JAR 文件,它爲衆多的消費者提供
共享代碼。持久化庫,或通用數據訪問,就是這些類庫之一。其中,一個流行的選擇是 Hibernate,它爲所有對象的持久化提供了通用接口。

也有數據操縱(data manipulation) 專用的語言,或者類似的儘可能無縫地進行數據操縱任務,以使其不對業務邏輯造成混亂。我們將會在下面探討的域特定
語言(domain-specific languages, DSLs)涉及這些方面。另外一個新的趨勢是將應用程序開發抽象出來,platform-as-a-service (PaaS)就是其最顯著的表現。
它提供了快速編寫應用所需的所有組件,包括應用程序服務器,相關的庫文件,數據庫,等待。

通過 PaaS, 仍需要編寫代碼並把它部署到 PaaS 所提供的基礎設施上。邏輯上,下一步是提供數據訪問 API, 應用程序不需要更進一步的設置就可以使用。
Google App Engine 服務就是這類服務之一,在它的服務上,用戶可以與數據存儲 API(作爲一個庫提供) 直接對話。這限制了應用程序的自由度,但假設
其存儲 API 足夠強大,並且對應用程序開發者的創造性沒有強加限制,這可以使開發和管理應用程序非常容易。

Hadoop 是非常強大而且靈活的系統。實際上,Hadoop 上的很多組件都可以被替換,並且對於 Hadoop, 更應將它當做一個思想體系,而非特殊技術的集合。
由於這些原因,一類新的活躍的框架正在興起是顯而易見的。類似於 Google App Engine 服務,Hadoop 提供了服務器組件用於接受部署到其上的應用程序
請求,並對底層服務抽象出接口,例如存儲服務。

令人感興趣的是,這類框架,將它們稱爲數據應用程序服務器(data application servers), 或者 data-as-a-service (DaaS), 包括 Hadoop 的原生服務,
它是數據優先的(data first)。就像智能手機,安裝實現業務場景的應用並運行在共享的數據所在的主機上。不需要耗費高昂的代價移動大量的數據來產生
結果。利用 HBase 作爲存儲引擎,可以讓這些框架最優利用很多內置的特性,例如,利用服務器端的協處理器降低選擇斷言以及分析功能等。這裏有一個
例子 Cask.

庫和框架的共同之處是抽象層的概念,它是一個通用的數據訪問 API 或 DSL。HBase 之上的框架也是如此,以及其它實現了 SQL 能力的通用存儲層。將會在
後面的章節中分別討論(see “SQL over NoSQL”), 它們提供了不同級別的 SQL 標準,例如 Impala, Hive, and Phoenix.

 

*
*
*

2. Gateway 客戶端 (Gateway Clients)
-----------------------------------------------------------------------------------------------------------------------------------------
第一組客戶端由 gateway 類型(gateway kind)組成, 向服務器按需發送客戶端調用,如 get, put, 或 delete 。基於所選擇的協議,通過所提供的 gateway
服務器,可以在自己的程序中訪問。另一方面,也可以利用所提供的存儲 API 來實現通用的,數據爲中心的解決方案。


2.1 原生 Java API (Native Java)
-----------------------------------------------------------------------------------------------------------------------------------------
原生 Java API 已在前面各個章節討論過,不需要啓動任何 gateway 服務器,直接使用 Table 或 BufferedMutator 與 HBase 服務器通信,經由原生 RPC
調用。

 

2.2 REST
-----------------------------------------------------------------------------------------------------------------------------------------
HBase 自帶了一個強大的 REST 服務器,完全支持客戶端和管理 API. 它也爲不同的消息格式提供支持,爲客戶端提供了多種選擇來與服務器通信。

 

■ 操作 (Operation)
-----------------------------------------------------------------------------------------------------------------------------------------
對基於 REST 的客戶端,要能夠連接到 HBase, 需要啓動合適的 gateway 服務器。這要通過所提供的腳本啓動。下面的命令展示瞭如何獲得命令行幫助,以
及以非守護進程的模式啓動 REST 服務器。

    $ bin/hbase rest
    usage: bin/hbase rest start [--infoport <arg>] [-p <arg>] [-ro]
    --infoport <arg> Port for web UI
    -p,--port <arg> Port to bind to [default: 8080]
    -ro,--readonly Respond only to GET HTTP method requests [default:false]

    To run the REST server as a daemon, execute bin/hbase-daemon.sh start|stop rest [--infoport <port>] [-p <port>] [-ro]
    $ bin/hbase rest start
    ^C

需要按下 Ctrl-C 來退出該進程。help 中說明了需要使用一個不同的腳本來以一個後臺進程運行服務器:

    $ bin/hbase-daemon.sh start rest
    starting rest, logging to /var/lib/hbase/logs/hbase-larsgeorgerest-<servername>.out

一旦服務器啓動了,需要在命令行上使用 curl 來驗證其是可操作的:

    $ curl http://<servername>:8080/
    testtable

    $ curl http://<servername>:8080/version
    rest 0.0.3 [JVM: Oracle Corporation 1.7.0_51-24.51-b03] [OS: Mac OS X 10.10.2 x86_64] [Server: jetty/6.1.26] [Jersey: 1.9]

獲取根 URL(root URL), 即 "/" 返回可用表的列表,例子中爲 testtable。通過 "/version" 獲取 REST 服務器版本,以及它運行所在機器相關的信息。

另一方面,可以打開由 REST 服務器提供的 web-based UI。可以通過 --infoport 命令行參數在啓動 REST 服務器時指定其他端口,或者修改配置屬性:
hbase.rest.info.port, 默認值爲 8085.


UI 界面具有的功能,與 HBase 提供的很多 web-based UIs 功能是共同的。中間部分提供有關服務器及其狀態信息。對於 REST 服務器,除了 HBase 版本,
編譯信息,和服務器啓動時間外,沒有太多信息。底部有到 HBase Wiki 的鏈接,對 REST API 進行解釋。在該頁面的頂部有幾個鏈接用於提供額外的功能。


    ● Home
    -------------------------------------------------------------------------------------------------------------------------------------
    鏈接到服務器的 Home 頁

    ● Local logs
    -------------------------------------------------------------------------------------------------------------------------------------
    打開一個列出本地日誌目錄的頁面,提供基於 web 訪問其他方式無法訪問的日誌文件    

    ● Log Level
    -------------------------------------------------------------------------------------------------------------------------------------
    這個頁面可以爲任何類查詢和設置日誌級別,或打包載入到服務器進程。
    
    ● Metrics Dump
    -------------------------------------------------------------------------------------------------------------------------------------
    HBase 中所有的服務器都有 metric 跟蹤其活動,通過這個鏈接可以 JSON 格式訪問。
    
    ● HBase Configuration
    -------------------------------------------------------------------------------------------------------------------------------------    
    打印出用於當前服務器進程的配置信息。
    
要停止作爲守護進程運行的 REST 服務器,調用同一個腳本,只是把 start 替換爲 stop 命令。

    $ bin/hbase-daemon.sh stop rest
    stopping rest..

可以根據自己的喜好啓動任意數量的 REST 服務器,並且,也可以利用一個負載均衡器在多個 REST 服務器間路由數據流量。由於 REST 是無狀態的,任何
所需的狀態都是作爲請求的一部分攜帶的,可以使用循環算法(或類似的方法)來分佈負載。

--readonly, 或 -ro 參數將服務器切換到只讀模式(read-only mode), 意思是隻對 HTTP GET 操作響應。最後,使用 -p 或 --port 參數爲服務器偵聽指定
一個不同的端口,默認爲 8080. 還有一些 REST 服務器在啓動時關注的屬性,下表列出它們及其默認值:


    Configuration options for the REST server
    +---------------------------------------+---------------+--------------------------------------------------------------------------
    | Property                                | Default        | Description
    +---------------------------------------+---------------+--------------------------------------------------------------------------
    | hbase.rest.dns.nameserver                | default        | Defines the DNS server used for the name lookup (NOTE:)
    +---------------------------------------+---------------+--------------------------------------------------------------------------
    | hbase.rest.dns.interface                | default        | Defines the network interface that the name is associated with (NOTE:)
    +---------------------------------------+---------------+--------------------------------------------------------------------------
    | hbase.rest.port                        | 8080            | Sets the HTTP port the server will bind to. Also settable per instance
    |                                        |                | with the -p and --port command-line parameter
    +---------------------------------------+---------------+--------------------------------------------------------------------------
    | base.rest.host                        | 0.0.0.0        | Defines the address the server is listening on. Defaults to the wildcard
    |                                        |                | address
    +---------------------------------------+---------------+--------------------------------------------------------------------------
    | hbase.rest.info.port                    | 8085            | Specifies the port the webbased UI will bind to. Also settable per instance
    |                                        |                | using the --infoport parameter
    +---------------------------------------+---------------+--------------------------------------------------------------------------
    | hbase.rest.info.bindAddress            | 0.0.0.0        | Sets the IP address the webbased UI is bound to. Defaults to the wildcard
    |                                        |                | address
    +---------------------------------------+---------------+--------------------------------------------------------------------------
    | hbase.rest.readonly                    | false            | Forces the server into normal or read-only mode. Also settable by the
    |                                        |                | --readonly, or -ro options
    +---------------------------------------+---------------+--------------------------------------------------------------------------
    | hbase.rest.threads.max                | 100            | Provides the upper boundary of the thread pool used by the HTTP server for
    |                                        |                | request handlers
    +---------------------------------------+---------------+--------------------------------------------------------------------------
    | hbase.rest.threads.min                | 2                | Same as above, but sets the lower boundary on number of handler threads.
    +---------------------------------------+---------------+--------------------------------------------------------------------------
    |hbase.rest.connection.cleanup-interval    |10000 (10secs)    | Defines how often the internal housekeeping task checks for expired
    |                                        |                | connections to the HBase cluster
    +---------------------------------------+---------------+--------------------------------------------------------------------------
    | hbase.rest.connection.max-idletime    |600000 (10mins)| Amount of time after which an unused connection is considered expired
    +---------------------------------------+---------------+--------------------------------------------------------------------------
    | hbase.rest.support.proxyuser            | false            | Flags if the server should support proxy users or not. This is used to
    |                                        |                | enable secure impersonation.
    +---------------------------------------+---------------+--------------------------------------------------------------------------


    NOTE:
    -------------------------------------------------------------------------------------------------------------------------------------
    These two properties are used in tandem to look up the server’s hostname using the given network interface and name server. The
    default value mean it uses whatever is configured on the OS level

 


■ 支持的格式 (Supported Formats)
-----------------------------------------------------------------------------------------------------------------------------------------
利用 HTTP 的 Content-Type 和 Accept 頭,可切換不同的格式用於發送或者返回給調用者。作爲一個示例,可以通過如下類似的 shell 命令在 HBase 中
創建一個表以並向其插入一行數據:

    hbase(main):001:0> create 'testtable', 'colfam1'
    0 row(s) in 0.6690 seconds

    => Hbase::Table - testtable
    hbase(main):002:0> put 'testtable', "\x01\x02\x03", 'col
    fam1:col1', 'value1'
    0 row(s) in 0.0230 seconds

    hbase(main):003:0> scan 'testtable'
    ROW COLUMN+CELL
    \x01\x02\x03 column=colfam1:col1, timestamp=1429367023394, value=value1
    1 row(s) in 0.0210 seconds

例子使用二進制行鍵(binary row key) 0x01 0x02 0x03 (十六進制數字) 插入一行。其中指定一個列族中的一個列,包含的值爲 value1。

    
    ● Plain 格式 (text/plain)
    -------------------------------------------------------------------------------------------------------------------------------------
    可以在一些操作中指定以文本格式返回數據。例如之前提到的 /version 操作:
    
    $ curl -H "Accept: text/plain" http://<servername>:8080/version
    rest 0.0.3 [JVM: Oracle Corporation 1.7.0_45-24.45-b08] [OS:Mac OS X 10.10.2 x86_64] [Server: jetty/6.1.26] [Jersey: 1.9]

    另一方面,對於比較複雜的返回值,純文本格式很難達到預期的結果:

        $ curl -H "Accept: text/plain" \
        http://<servername>:8080/testtable/%01%02%03/colfam1:col1
        <html>
        <head>
        <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"/>
        <title>Error 406 Not Acceptable</title>
        </head>
        <body><h2>HTTP ERROR 406</h2>
        <p>Problem accessing /testtable/%01%02%03/colfam1:col1. Reason:
        <pre> Not Acceptable</pre></p>
        <hr /><i><small>Powered by Jetty://</small></i><br/>
        <br/>
        ...
        <br/>
        </body>
        </html>

    這是由於這樣的事實,服務器不能對如何格式化一個複雜的純文本格式結果值進行假設。用戶需要使用一種自身能夠表達嵌套信息的格式。

    NOTE:
    -------------------------------------------------------------------------------------------------------------------------------------
    示例中使用的行鍵是二進制形式的,由三個字節組成。可以通過使用 URL 編碼對行鍵編碼,以使用 REST 來訪問這些字節,編碼後的行鍵爲 %01%02%03
    因此獲取一個 cell 的整個 URL 爲:
    
        http://<servername>:8080/testtable/%01%02%03/colfam1:col1

    
    ● XML (text/xml) 格式
    -------------------------------------------------------------------------------------------------------------------------------------
    在存儲或者獲取數據時,XML 被作爲默認的的格式。例如,在沒有指定特定的 Accept 頭來獲取示例中的行時,會接收到:
    
        $ curl http://<servername>:8080/testtable/%01%02%03/colfam1:col1
        
        <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
        <CellSet>
            <Row key="AQID">
                <Cell column="Y29sZmFtMTpjb2wx" timestamp="1429367023394">dmFsdWUx</Cell>
            </Row>
        </CellSet>
    
    返回的格式默認爲 XML. 列名(column name) 和實際的值都經過了 Base64 編碼。下面是它們各自的 schema 部分:

    <element name="Row" type="tns:Row"></element>
        <complexType name="Row">
            <sequence>
                <element name="key" type="base64Binary"></element>
                <element name="cell" type="tns:Cell" maxOccurs="unbounded" minOccurs="1"></element>
            </sequence>
        </complexType>
    <element name="Cell" type="tns:Cell"></element>
    <complexType name="Cell">
        <sequence>
            <element name="value" maxOccurs="1" minOccurs="1">
                <simpleType>
                    <restriction base="base64Binary">
                </simpleType>
            </element>
        </sequence>
        <attribute name="column" type="base64Binary" />
        <attribute name="timestamp" type="int" />
    </complexType>

    所有出現 base64Binary 的地方,REST 服務器都返回編碼的數據。這樣可以安全地傳輸二進制數據,可能包含在鍵或者值中。對發送到 REST 服務器
    的數據也是如此。

    在控制檯上使用 base64 命令快速測試以顯示正確的內容:

        $ echo AQID | base64 -D | hexdump
        0000000 01 02 03
        
        $ echo Y29sZmFtMTpjb2wx | base64 -D
        colfam1:col1

        $ echo dmFsdWUx | base64 -D
        value1

    很明顯,這隻在命令行上驗證有用。在自己的代碼中,可以使用任何可用的 Base64 實現來解碼返回的值。

    
    ● JSON (application/json) 格式
    -------------------------------------------------------------------------------------------------------------------------------------
    類似於 XML, 要求數據使用 JSON 格式,只是簡單地要求設置 Accept 頭:
    
    $ curl -H "Accept: application/json" http://<servername>:8080/testtable/%01%02%03/colfam1:col1
    {
        "Row": [{
            "key": "AQID",
            "Cell": [{
                "column": "Y29sZmFtMTpjb2wx",
                "timestamp": 1429367023394,
                "$": "dmFsdWUx"
            }]
        }]
    }
    
    對值的編碼與 XML 相同,即對任何可能包含二進制數據的值都使用 Base64 編碼。與 XML 格式顯著的不同是 JSON 格式沒有無名的數據段(data fields)
    在 XML 中,cell 數據是在 Cell 標記中返回的,而 JSON 必須指定 key/value 對,因此沒有與之對應的字段名稱。由於這個原因,JSON 使用一個特殊
    的名稱 "$". "$" 字段就是 cell 的值。在上面的例子中,使用了:
    
        "$":"dmFsdWUx"
        
    需要查詢 "$" 域(field)以得到 Base64 編碼的數據。
    
    
    ● Protocol Buffer (application/x-protobuf) 格式
    -------------------------------------------------------------------------------------------------------------------------------------    
    REST 應用程序一個有趣的地方是能夠切換編碼,由於 Protocol Buffer 沒有原生 RPC 棧,因此 HBase REST 服務器提供了對其編碼的支持。
    
    獲取 Protocol Buffer 編碼的返回結果,要求匹配 Accept 頭:
    
        $ curl -H "Accept: application/x-protobuf" http://<servername>:8080/testtable/%01%02%03/colfam1:col1 | hexdump -C
    
        ...
        00000000 0a 24 0a 03 01 02 03 12 1d 12 0c 63 6f 6c 66 61 |.
        $.........colfa|
        00000010 6d 31 3a 63 6f 6c 31 18 a2 ce a7 e7 cc 29 22 06 |
        m1:col1......)".|
        00000020 76 61 6c 75 65 31 |
        value1|
    
    使用 hexdump 命令可以二進制格式打印出編碼的消息。需要一個 Protocol Buffer 解碼器以結構化的方式訪問實際的數據。
    
    
    ● Raw binary (application/octet-stream) 格式
    -------------------------------------------------------------------------------------------------------------------------------------    
    最後,可以按其原始形式轉儲(dump)數據,而忽略其結構數據。在下面的控制檯命令中,只有存儲在 cell 中的數據返回:
    
        $ curl -H "Accept: application/octet-stream" http://<servername>:8080/testtable/%01%02%03/colfam1:col1 | hexdump -C
        00000000 76 61 6c 75 65 31 |value1|

    
    NOTE:
    -------------------------------------------------------------------------------------------------------------------------------------    
    取決於請求的格式,REST 服務器將結構化的數據放到自定義的頭中。例如,對於原始的 get 請求,響應頭類似如下:
    
        HTTP/1.1 200 OK
        Content-Length: 6
        X-Timestamp: 1429367023394
        Content-Type: application/octet-stream
    
    cell 的時間戳已經被移到頭部作爲 X-Timestamp, 由於行和列的鍵是請求 URI 的一部分,因此它們在響應中被忽略掉,以防止沒必要的數據傳輸。

 

■ REST Java 客戶端 (REST Java Client)
-----------------------------------------------------------------------------------------------------------------------------------------
REST 服務器也帶有全面的 Java 客戶端 API, 位於 org.apache.hadoop.hbase.rest.client 包。其核心類是 RemoteHTable 和 RemoteAdmin, 下面示例
展示了 RemoteHTable 類的使用。

示例: Example of using the REST client classes

    Cluster cluster = new Cluster();
    //Set up a cluster list adding all known REST server hosts
    cluster.add("localhost", 8080);

    //Create the client handling the HTTP communication
    Client client = new Client(cluster);

    //Create a remote table instance, wrapping the REST access into a familiar interface
    RemoteHTable table = new RemoteHTable(client, "testtable");

    //Perform a get operation as if it were a direct HBase connection
    Get get = new Get(Bytes.toBytes("row-30"));
    get.addColumn(Bytes.toBytes("colfam1"), Bytes.toBytes("col-3"));
    Result result1 = table.get(get);
    System.out.println("Get result1: " + result1);

    Scan scan = new Scan();
    scan.setStartRow(Bytes.toBytes("row-10"));
    scan.setStopRow(Bytes.toBytes("row-15"));
    scan.addColumn(Bytes.toBytes("colfam1"), Bytes.toBytes("col-5"));

    //Scan the table, again, the same approach as if using the native Java API.
    ResultScanner scanner = table.getScanner(scan);
    for (Result result2 : scanner) {
        System.out.println("Scan row[" + Bytes.toString(result2.getRow())
        +
        "]: " + result2);
    }

運行示例程序需要 REST 服務器已啓動並且偵聽在指定的端口上。如果在不同的機器和端口上運行服務器,要先調整 Cluster 實例 add 方法參數值。
輸出類似於:

    Adding rows to table...
    Get result1: keyvalues={row-30/colfam1:col-3/1429376615162/Put/vlen=8/seqid=0}
    Scan row[row-10]:
    keyvalues={row-10/colfam1:col-5/1429376614839/Put/vlen=8/seqid=0}
    Scan row[row-100]:
    keyvalues={row-100/colfam1:col-5/1429376616162/Put/vlen=9/
    seqid=0}
    Scan row[row-11]:
    keyvalues={row-11/colfam1:col-5/1429376614856/Put/vlen=8/seqid=0}
    Scan row[row-12]:
    keyvalues={row-12/colfam1:col-5/1429376614873/Put/vlen=8/seqid=0}
    Scan row[row-13]:
    keyvalues={row-13/colfam1:col-5/1429376614891/Put/vlen=8/seqid=0}
    Scan row[row-14]:
    keyvalues={row-14/colfam1:col-5/1429376614907/Put/vlen=8/seqid=0}

RemoteHTable 是與多個 REST 服務器對話的便捷方式,而且能夠使用正常的 Java 客戶端類,例如 Get, Scan.

    NOTE:
    -------------------------------------------------------------------------------------------------------------------------------------
    當前的 REST 的 Java 客戶端實現內部使用了 Protocol Buffer 編碼與遠程 REST 服務器通信,它是服務器所支持的最緊湊的協議,因而提供了最好的
    帶寬使用效率。

 

2.3 Thrift
-----------------------------------------------------------------------------------------------------------------------------------------
Apache Thrift 是由 C++ 寫的,但爲很多編程語言提供了模式編譯器(schema compilers), 包括 Java, C++, Perl, PHP, Python, Ruby, 等待。一旦有了
編譯好的 schema, 就可以與實現了一種或多種語言的系統 透明地交換信息。


■ 安裝 (Installation)
-----------------------------------------------------------------------------------------------------------------------------------------
在能使用 Thrift 之前,首先需要安裝它,安裝時最好使用適合操作系統的二進制安裝包,如果沒有就需要從源代碼編譯。

從網站下載源碼 tar 包,並解壓到常用目錄:

    $ wget http://www.apache.org/dist/thrift/0.9.2/thrift-0.9.2.tar.gz
    $ tar -xzvf thrift-0.9.2.tar.gz -C /opt
    $ rm thrift-0.9.2.tar.gz

安裝依賴包,也就是 Automake, LibTool, Flex, Bison,以及 Boost 類庫:

    $ sudo apt-get install build-essential automake libtool flex bison libboost

構建並安裝    Thrift:

    $ cd /opt/thrift-0.9.2
    $ ./configure
    $ make
    $ sudo make install

安裝好之後,驗證其是否成功:

    $ thrift -version
    Thrift version 0.9.2

一旦有了 Thrift 安裝,需要編譯一個 schema 到所選擇的編程語言。HBase 自帶了一個 schema 文件用於它的客戶端 API 和 管理 API. 需要使用 Thrift
二進制文件爲開發環境創建封裝。

在通過 Thrift 訪問 HBase 之前,必須啓動 ThriftServer。

 

■ Thrift 操作 (Thrift Operations)
-----------------------------------------------------------------------------------------------------------------------------------------
啓動 Thrift server 通過其提供的腳本實現。可以給命令行加 -h 選項,或者忽略所有選項以獲得幫助。

    $ bin/hbase thrift
    usage: Thrift [-b <arg>] [-c] [-f] [-h] [-hsha | -nonblocking |
    -threadedselector | -threadpool] [--infoport <arg>] [-k <arg>] [-m <arg>] [-p <arg>] [-q <arg>] [-w <arg>]
    -b,--bind <arg> Address to bind the Thrift server to.[default:0.0.0.0]
    -c,--compact Use the compact protocol
    -f,--framed Use framed transport
    -h,--help Print help information
    -hsha Use the THsHaServer This implies the framed transport.
    --infoport <arg> Port for web UI
    -k,--keepAliveSec <arg> The amount of time in secods to keep a thread alive when idle in TBoundedThreadPoolServer
    -m,--minWorkers <arg> The minimum number of worker threads for TBoundedThreadPoolServer
    -nonblocking Use the TNonblockingServer This implies the framed transport.
    -p,--port <arg> Port to bind to [default: 9090]
    -q,--queue <arg> The maximum number of queued requests in TBoundedThreadPoolServer
    -threadedselector Use the TThreadedSelectorServer This implies the framed transport.
    -threadpool Use the TBoundedThreadPoolServerThis is the default.
    -w,--workers <arg> The maximum number of worker threads for TBoundedThreadPoolServer
    To start the Thrift server run 'bin/hbase-daemon.sh start thrift'
    To shutdown the thrift server run 'bin/hbase-daemon.sh stop thrift' or send a kill signal to the thrift server pid

有很多選項可以選擇。type of server, protocol, 以及 transport 是由客戶端強制使用的,因爲不是所有的語言實現都支持它們。

使用默認選項,以非守護進程模式啓動 Thrift server:

    $ bin/hbase thrift start
    ^C

需要按下 Ctrl-C 退出進程。要以後臺進程的模式運行,需要使用另一個腳本:

    $ bin/hbase-daemon.sh start thrift
    starting thrift, logging to /var/lib/hbase/logs/hbase-larsgeorge-thrift-<servername>.out

停止運行於守護進程模式的 Thrift server:

    $ bin/hbase-daemon.sh stop thrift
    stopping thrift..

一旦啓動了 Thrift server,就可以打開 Thrift server 提供的 web-based UI。可以通過 --infoport 命令行參數,或者 hbase.thrift.info.port 配置
屬性指定其端口,默認設置爲 9095.

Thrift web-based UI 擁有的功能與許多 HBase 提供的 web-based UI 類似。

Thrift server 提供了操作 HBase 表所要求的所有操作。可以啓動多個 Thrift server,並且,可以通過一個負載均衡器在服務器之間路由數據流。可以
使用 -p 或 --port 參數指定偵聽不同的端口,默認爲 9090.

還有一些配置屬性在 Thrift server 啓動時需要關注,如下:

    Configuration options for the Thrift server
    +-------------------------------------------------------+-------------------+-------------------------------------------------
    | Property                                                | Default            | Description
    +-------------------------------------------------------+-------------------+-------------------------------------------------
    | hbase.regionserver.thrift.port                        | 9090                | Sets the port the server will bind to. Also
    |                                                        |                    | settable per instance with the -p or --port
    |                                                        |                    | command-line parameter.(NOTE:)
    +-------------------------------------------------------+-------------------+-------------------------------------------------
    | hbase.regionserver.thrift.ipaddress                    | 0.0.0.0            | Defines the address the server is listening on.
    |                                                        |                    | Defaults to the wildcard address. Set with -b,
    |                                                        |                    | --bind per instance on the command-line(NOTE:)
    +-------------------------------------------------------+-------------------+-------------------------------------------------
    | hbase.thrift.info.port                                | 9095                | Specifies the port the web-based UI will bind to.
    |                                                        |                    |Also settable per instance using --infoport parameter
    +-------------------------------------------------------+-------------------+-------------------------------------------------
    | hbase.thrift.info.bindAddress                            | 0.0.0.0            | Sets the IP address the web-based UI is bound to.
    |                                                        |                    | Defaults to the wildcard address
    +-------------------------------------------------------+-------------------+-------------------------------------------------
    | hbase.regionserver.thrift.server.type                    | threadpool        | Sets the Thrift server type in non-HTTP mode.
    +-------------------------------------------------------+-------------------+-------------------------------------------------
    | hbase.regionserver.thrift.compact                        | false                | Enables the compact protocol mode if set to true.
    |                                                        |                    | Default means binary mode instead. Also settable per
    |                                                        |                    | instance with -c, or --compact.
    +-------------------------------------------------------+-------------------+-------------------------------------------------
    | hbase.regionserver.thrift.framed                        | false                | Sets the transport mode to framed. Otherwise the
    |                                                        |                    | standard transport is used. Framed cannot be used
    |                                                        |                    | in secure mode. When using the hsha or nonblocking
    |                                                        |                    | server type, framed transport is always used
    |                                                        |                    | irrespective of this configuration property. Also  
    |                                                        |                    | settable per instance with -f, or --framed.
    +-------------------------------------------------------+-------------------+-------------------------------------------------
    | hbase.regionserver.thrift.framed.max_frame_size_in_mb    | 2097152 (2MB)        | The maximum frame size when framed transport mode is
    |                                                        |                    | enabled
    +-------------------------------------------------------+-------------------+-------------------------------------------------
    | hbase.thrift.minWorkerThreads                            | 16                | Sets the minimum amount of worker threads to keep,
    |                                                        |                    | should be increased for production use (for example,
    |                                                        |                    | to 200). Settable on the command-line with -m, or
    |                                                        |                    | --minWorkers
    +-------------------------------------------------------+-------------------+-------------------------------------------------
    | hbase.thrift.maxWorkerThreads                            | 1000                | Sets the upper limit of worker threads. Settable
    |                                                        |                    | on the command-line with -w, or --workers.
    +-------------------------------------------------------+-------------------+-------------------------------------------------
    | hbase.thrift.maxQueuedRequests                        | 1000                | Maximum number of request to queue when workers
    |                                                        |                    | are all busy. Can be set with -q, and --queue per
    |                                                        |                    | instance
    +-------------------------------------------------------+-------------------+-------------------------------------------------
    | hbase.thrift.threadKeepAliveTimeSec                    | 60 (secs)            | Amount of time an extraneous idle worker is kept
    |                                                        |                    | before it is discarded. Also settable with -k, or
    |                                                        |                    | --keepAliveSec
    +-------------------------------------------------------+-------------------+-------------------------------------------------
    | hbase.regionserver.thrift.http                        | false                | Flag that determines if the server should run in
    |                                                        |                    | HTTP or native mode.
    +-------------------------------------------------------+-------------------+-------------------------------------------------
    | hbase.thrift.http_threads.max                            | 100                | Provides the upper boundary of the thread pool used
    |                                                        |                    | by the HTTP server for request handlers
    +-------------------------------------------------------+-------------------+-------------------------------------------------
    | hbase.thrift.http_threads.min                            | 2                    | Same as above, but sets the lower boundary on number
    |                                                        |                    | of handler threads
    +-------------------------------------------------------+-------------------+-------------------------------------------------
    | hbase.thrift.ssl.enabled                                | false                | When HTTP mode is enabled, this flag sets the SSL mode.
    +-------------------------------------------------------+-------------------+-------------------------------------------------
    | hbase.thrift.ssl.keystore.store                        | ""                | When SSL is enabled, sets the key store file
    +-------------------------------------------------------+-------------------+-------------------------------------------------
    | hbase.thrift.ssl.keystore.password                    | null                | When SSL is enabled, sets the password to unlock
    |                                                        |                    | the key store file
    +-------------------------------------------------------+-------------------+-------------------------------------------------
    | hbase.thrift.ssl.keystore.keypassword                    | null                | When SSL is enabled, sets the password to retrieve
    |                                                        |                    | the keys from the key store
    +-------------------------------------------------------+-------------------+-------------------------------------------------
    | hbase.thrift.security.qop                                | ""                | Can be one of auth, auth-int, or auth-conf to set
    |                                                        |                    | the SASL qualityof-protection (QoP)
    +-------------------------------------------------------+-------------------+-------------------------------------------------
    | hbase.thrift.support.proxyuser                        | false                | Flags if the server should support proxy users or not.
    |                                                        |                    | This is used to enable secure impersonation
    +-------------------------------------------------------+-------------------+-------------------------------------------------
    | hbase.thrift.kerberos.principal                        | <hostname>        | Can be used to set the Kerberos principal to use
    |                                                        |                    | in secure mode
    +-------------------------------------------------------+-------------------+-------------------------------------------------
    | hbase.thrift.keytab.file                                | ""                | Specifies the Kerberos keytab file for secure operation
    +-------------------------------------------------------+-------------------+-------------------------------------------------
    | hbase.regionserver.thrift.coalesceIncrement            | false                | Enables the coalesce mode for increments, which is
    |                                                        |                    | a delayed, batch increment operation
    +-------------------------------------------------------+-------------------+-------------------------------------------------
    | hbase.thrift.filters                                    | ""                | Loads filter classes into the server process for
    |                                                        |                    | subsequent use
    +-------------------------------------------------------+-------------------+-------------------------------------------------
    | hbase.thrift.connection.cleanup-interval                | 10000 (10 secs)    | Defines how often the internal housekeeping task
    |                                                        |                    | checks for expired connections to the HBase cluster.
    +-------------------------------------------------------+-------------------+-------------------------------------------------
    | hbase.thrift.connection.max-idletime                    | 600000 (10 mins)    | Amount of time after which an unused connection is
    |                                                        |                    | considered expired
    +-------------------------------------------------------+-------------------+-------------------------------------------------


    NOTE:
    -------------------------------------------------------------------------------------------------------------------------------------
    These two properties are used in tandem to look up the server’s hostname using the     given network interface and name server. The
    default value mean it uses whatever is configured on the OS level
    
    
Thrift native 模式中有幾個服務器類型(server type):

    ● 非阻塞 (nonblocking)
    -------------------------------------------------------------------------------------------------------------------------------------
    使用 TNonblockingServer 類,它是基於 Java NIO 的 non-blocking I/O 技術,選擇器線程(selector thread)處理實際的請求。每服務器實例可設置
    使用 -nonblocking 參數。


    ● hsha
    -------------------------------------------------------------------------------------------------------------------------------------
    使用 THsHaServer 類,實現一個 Half-Sync/Half-Async(HsHa)服務器。與非阻塞服務器不同的是,使用一個線程來接受連接,但使用一個線程池來處理
    工作線程。每服務器實例可設置,使用 -hsha 參數。


    ● threadedselector
    -------------------------------------------------------------------------------------------------------------------------------------
    在 HsHa 服務器基礎上的擴展,維護兩個線程池,其中之一用於網絡 I/O(selection), 另一個用於處理工作線程。使用 TThreadedSelectorServer 類。
    每服務器實例可設置,使用 -threadedselector 參數。
    

    ● threadpool
    -------------------------------------------------------------------------------------------------------------------------------------
    一個線程用於接受連接,然後將實際的工作在 ExecutorService 中調度。每一個連接專用於一個客戶端,因此在高併發的使用場景需要大量的線程。
    使用 TBoundedThreadPoolServer 類,是對 ThriftTThreadPoolServer 類的自定義實現。每服務器實例可設置,使用 -threadpool 參數。

默認的 threadpool 類型對於生產環境是一個很好的選擇,它聯合使用了多個被實踐驗證了的技術。


■ 示例:PHP
-----------------------------------------------------------------------------------------------------------------------------------------
HBase 不僅自帶了所需要的 Thrift schema 文件,而且爲多種編程語言提供了客戶端示例。這裏使用 PHP 實現以演示所需的步驟。

在開始之前,有幾點需要注意:


    ● 需要爲 web 服務器啓用 PHP 支持。
    -------------------------------------------------------------------------------------------------------------------------------------


    ● HBase 自帶了預編譯好的 PHP Thrift 模塊,因此可以忽略下面的步驟 1,即新生成 Thrift 模塊,其結果是一樣的。代碼在HBase 的hbase-examples
    目錄下。
    -------------------------------------------------------------------------------------------------------------------------------------


    ● 所包含的 DemoClient.php 不是最新的,例如,使用空行鍵測試是不允許的,而且使用了非 UTF-8 行鍵。這兩個檢查都會失敗,因此需要小心修復
    PHP 文件。
    -------------------------------------------------------------------------------------------------------------------------------------


步驟 1:
-----------------------------------------------------------------------------------------------------------------------------------------
複製 HBase 所提供的 schema 文件並編譯必要的 PHP 源文件

    $ cp -r $HBASE_HOME/hbase-thrift/src/main/resources/org/apache/hadoop/hbase/thrift ~/thrift_src
    $ cd thrift_src/
    $ thrift -gen php Hbase.thrift

在 thrift_src 目錄中會產生一個 gen-php 目錄,其中包含兩個生成的訪問 HBase 所需的 PHP 文件:

    $ ls -l gen-php/Hbase/
    total 920
    -rw-r--r-- 1 larsgeorge staff 416357 Apr 20 07:46 Hbase.php
    -rw-r--r-- 1 larsgeorge staff 52366 Apr 20 07:46 Types.php

如果忽略這個步驟,可以從 HBase 源碼包的 hbase-examples 目錄複製 HBase 所提供的,預先編譯好的 PHP 文件:

    $ ls -lR $HBASE_HOME/hbase-examples/src/main/php
    total 24
    -rw-r--r-- 1 larsgeorge admin 8438 Jan 25 10:47 DemoClient.php
    drwxr-xr-x 3 larsgeorge admin 102 May 22 2014 gen-php
    /usr/local/hbase-1.0.0-src/hbase-examples/src/main/php/gen-php:
    total 0
    drwxr-xr-x 4 larsgeorge admin 136 Jan 25 10:47 Hbase
    /usr/local/hbase-1.0.0-src/hbase-examples/src/main/php/gen-php/Hbase:
    total 800
    -rw-r--r-- 1 larsgeorge admin 366528 Jan 25 10:47 Hbase.php


步驟 2:
-----------------------------------------------------------------------------------------------------------------------------------------
生成的文件還需要 Thrift 提供的 PHP 輔助文件,這些文件需要和生成的文件一起拷貝到 web 服務器的文檔根目錄:

    $ cd /opt/thrift-0.9.2
    $ sudo mkdir $DOCUMENT_ROOT/thrift/
    $ sudo cp src/*.php $DOCUMENT_ROOT/thrift/
    $ sudo cp -r lib/Thrift/* $DOCUMENT_ROOT/thrift/
    $ sudo mkdir $DOCUMENT_ROOT/thrift/packages
    $ sudo cp -r ~/thrift_src/gen-php/Hbase $DOCUMENT_ROOT/thrift/packages/    
    
HBase 自帶的 DemoClient.php 文件要使用生成的文件與服務器通信,因此也將這個文件拷貝到 web 服務器的根目錄:

    $ sudo cp $HBASE_HOME/hbase-examples/src/main/php/DemoClient.php $DOCUMENT_ROOT/    

需要編輯 DemoClient.php 文件,在文件開始部分調整如下字段:

    # Change this to match your thrift root
    $GLOBALS['THRIFT_ROOT'] = 'thrift';
    ...
    # According to the thrift documentation, compiled PHP thrift libraries should
    # reside under the THRIFT_ROOT/packages directory. If these compiled libraries
    # are not present in this directory, move them there from gen-php/.
    require_once( $GLOBALS['THRIFT_ROOT'].'/packages/Hbase/
    Hbase.php' );
    ...
    $socket = new TSocket( 'localhost', 9090 );
    ...

調整之後,打開瀏覽器指向 demo 頁面,如:

    http://<webserver-address>/DemoClient.php

將會載入頁面,並輸出如下信息:

    scanning tables...
    found: testtable
    creating table: demo_table
    column families in demo_table:
    column: entry:, maxVer: 10
    column: unused:, maxVer: 3
    Starting scanner...
    ...

C++, Java, Perl,Python, and Ruby 中也有相同的 demo 客戶端。使用的步驟相同:啓動 Thrift 服務器,編譯 schema 定義文件到指定的語言,啓動客戶
端。根據不同的語言,需要將生成的代碼放到合適的位置。

 

■ 示例:Java
-----------------------------------------------------------------------------------------------------------------------------------------
HBase 已經自帶了生成的 Java 類用於與 Thrift 服務器通信,當然也可以從 schema 文件重新生成。下面的示例使用這些類與 Thrift 服務器通信,確保
Thrift 服務器已啓動並在 9090 端口上偵聽:

示例: Example using the Thrift generated client API

    private static final byte[] TABLE = Bytes.toBytes("testtable");
    private static final byte[] ROW = Bytes.toBytes("testRow");
    private static final byte[] FAMILY1 = Bytes.toBytes("testFamily1");
    private static final byte[] FAMILY2 = Bytes.toBytes("testFamily2");
    private static final byte[] QUALIFIER = Bytes.toBytes("testQualifier");
    private static final byte[] COLUMN = Bytes.toBytes("testFamily1:testColumn");
    private static final byte[] COLUMN2 = Bytes.toBytes("testFamily2:testColumn2");
    private static final byte[] VALUE = Bytes.toBytes("testValue");


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

        TTransport transport = new TSocket("0.0.0.0", 9090, 20000);
        TProtocol protocol = new TBinaryProtocol(transport, true, true);

        //Create a connection using the Thrift boilerplate classes.
        Hbase.Client client = new Hbase.Client(protocol);
        transport.open();

        ArrayList<ColumnDescriptor> columns = new ArrayList<ColumnDescriptor>();

        //Create two column descriptor instances.
        ColumnDescriptor cd = new ColumnDescriptor();
        cd.name = ByteBuffer.wrap(FAMILY1);
        columns.add(cd);

        cd = new ColumnDescriptor();
        cd.name = ByteBuffer.wrap(FAMILY2);
        columns.add(cd);

        //Create the test table
        client.createTable(ByteBuffer.wrap(TABLE), columns);

        ArrayList<Mutation> mutations = new ArrayList<Mutation>();
        mutations.add(new Mutation(false, ByteBuffer.wrap(COLUMN), ByteBuffer.wrap(VALUE), true));
        mutations.add(new Mutation(false, ByteBuffer.wrap(COLUMN2), ByteBuffer.wrap(VALUE), true));
        //Insert a test row
        client.mutateRow(ByteBuffer.wrap(TABLE), ByteBuffer.wrap(ROW), mutations, null);

        TScan scan = new TScan();
        //Scan with an instance of TScan. This is the most convenient approach. Print the results in a loop.
        int scannerId = client.scannerOpenWithScan(ByteBuffer.wrap(TABLE), scan, null);
        for (TRowResult result : client.scannerGet(scannerId)) {
            System.out.println("No. columns: " + result.getColumnsSize());
            for (Map.Entry<ByteBuffer, TCell> column : result.getColumns().entrySet()) {
                System.out.println("Column name: " + Bytes.toString(column.getKey().array()));
                System.out.println("Column value: " + Bytes.toString(column.getValue().getValue()));
            }
        }
        client.scannerClose(scannerId);

        ArrayList<ByteBuffer> columnNames = new ArrayList<ByteBuffer>();
        columnNames.add(ByteBuffer.wrap(FAMILY1));

        //Scan again, but with another Thrift method. In addition, set the columns to a specific family only.
        //Also print out the results in a loop.
        scannerId = client.scannerOpen(ByteBuffer.wrap(TABLE), ByteBuffer.wrap(Bytes.toBytes("")), columnNames, null);
        for (TRowResult result : client.scannerGet(scannerId)) {
            System.out.println("No. columns: " + result.getColumnsSize());
            for (Map.Entry<ByteBuffer, TCell> column : result.getColumns().entrySet()) {
                System.out.println("Column name: " + Bytes.toString(column.getKey().array()));
                System.out.println("Column value: " + Bytes.toString(column.getValue().getValue()));
            }
        }
        client.scannerClose(scannerId);
        System.out.println("Done.");
        
        //Close the connection after everything is done
        transport.close();
    }

輸出:
    No. columns: 2
    Column name: testFamily1:testColumn
    Column value: testValue
    Column name: testFamily2:testColumn2
    Column value: testValue
    No. columns: 1
    Column name: testFamily1:testColumn
    Column value: testValue
    Done.

 

2.4 Thrift2
-----------------------------------------------------------------------------------------------------------------------------------------
由於 HBase 客戶端 API 與 0.90 版本有了很大的變化,因此,Thrift API在很多地方與當前的 HBase 版本都已不同步了。Thrift2 實現了一個新的Thrift
gateway 服務器版本。它使用了當前的 HBase 客戶端 API, 因而對於熟悉原生 Java API 的 HBase 開發者來說感覺上更加自然。

整體來說,Thrift2 服務器使用與原始的 Thrift 服務器類似的方式,可以從 thrift2 命令行選項看到其類似的操作:

    $ bin/hbase thrift2
    
    usage: Thrift [-b <arg>] [-c] [-f] [-h] [-hsha | -nonblocking |
    -threadpool] [--infoport <arg>] [-p <arg>]
    -b,--bind <arg> Address to bind the Thrift server to. [default:0.0.0.0]
    -c,--compact Use the compact protocol
    -f,--framed Use framed transport
    -h,--help Print help information
    -hsha Use the THsHaServer. This implies the framed transport.
    --infoport <arg> Port for web UI
    -nonblocking Use the TNonblockingServer. This implies the framed transport.
    -p,--port <arg> Port to bind to [default: 9090]
    -threadpool Use the TThreadPoolServer. This is the default.
    To start the Thrift server run 'bin/hbase-daemon.sh start thrift2'
    To shutdown the thrift server run 'bin/hbase-daemon.sh stop thrift2' or send a kill signal to the thrift server pid

使用默認選項,以非守護進程模式運行:

    $ bin/hbase thrift2 start
    ^C

以守護進程運行:

    $ bin/hbase-daemon.sh start thrift2
    starting thrift2, logging to /var/lib/hbase/logs/hbase-larsgeorge-thrift2-<servername>.out

停止守護進程:

    $ bin/hbase-daemon.sh stop thrift2
    stopping thrift2.

 

2.5 SQL over NoSQL
-----------------------------------------------------------------------------------------------------------------------------------------
運行於 NoSQL 之上的 SQL 框架,使 HBase 看起來很像傳統的 RDBMS: 可以有事務、索引、引用完整性,以及其它知名的特性,所有這些都建立在非 SQL
的系統之上。這些框架在不同級別上實現完整性,圍繞 HBase 本身添加了一些服務,重新加入一些數據庫相關的特性。下面是一些知名的項目:

    
    ■ Phoenix
    -------------------------------------------------------------------------------------------------------------------------------------
    Apache Phoenix 項目提供最純粹的 HBase 的集成。該框架使用很多高級的特性,來優化對HBase 表的 SQL 查詢,包括輔助索引的協處理器,以及過濾


    ■ Trafodion
    -------------------------------------------------------------------------------------------------------------------------------------
    由 HP 作爲開源軟件開發,是一個聯合了現有數據庫技術的系統,使用 HBase 作爲存儲層。
    
    
    ■ Impala
    -------------------------------------------------------------------------------------------------------------------------------------
    另一個開源的, Apache 許可證的項目。其主要用於執行對存儲在 HDFS 中的數據進行交互式查詢,它也有直接訪問 HBase 表的能力。
    
    
    ■ Hive with Tez/Spark
    -------------------------------------------------------------------------------------------------------------------------------------
    最初用於 Hadoop batch 框架以執行數據處理。通過使用其它引擎替換 MapReduce 的選項,例如 Tez 或 Spark, 可以對 HBase 表運行基於 HiveQL 的交互式查詢。

 

系列目錄:

HBase 客戶端類型 (一)

HBase 客戶端類型 (二)

HBase 客戶端類型 (三)

HBase 客戶端類型 (四)

 

參考:

    《HBase - The Definitive Guide - 2nd Edition》Early release —— 2015.7 Lars George

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章