hbase-client java 程式的編譯與執行

完成hbase從即架設之後,
接下來, 就要利用hbase來存取資料,
在hbase的架構中, 原生的存取方式有三種:
thrift, java program 以及 hbase shell,

在這篇文章中, 我們假設hbase中已經有一個myHBaseTable,
在myHBaseTable中, 只有一個column: myFamily,
接著, 我們想執行以下的程式:

import java.io.IOException;

import org.apache.hadoop.conf.Configuration;

import org.apache.hadoop.hbase.client.Get;
import org.apache.hadoop.hbase.client.HTable;
import org.apache.hadoop.hbase.client.Put;
import org.apache.hadoop.hbase.client.Result;
import org.apache.hadoop.hbase.client.ResultScanner;
import org.apache.hadoop.hbase.client.Scan;
import org.apache.hadoop.hbase.util.Bytes;

public class hbasetest {
    public static Configuration conf;
    static {
        conf = HBaseConfiguration.create();
        conf.set("hbase.zookeeper.property.clientPort", "2222");
        conf.set("hbase.zookeeper.quorum", "master.hbase.mbwcl.nctu.edu.tw");
    }
    public static void main(String[] args) throws IOException {

        HTable table = new HTable(conf, "myHBaseTable");
        Put p = new Put(Bytes.toBytes("myRow"));
        p.add(Bytes.toBytes("myFamily"), Bytes.toBytes("someQualifier"),
                Bytes.toBytes("Some Value"));
        table.put(p);
        Get g = new Get(Bytes.toBytes("myRow"));
        Result r = table.get(g);
        byte[] value = r.getValue(Bytes.toBytes("myFamily"),
                Bytes.toBytes("someQualifier"));
        String valueStr = Bytes.toString(value);
        System.out.println("GET: " + valueStr);

        Scan s = new Scan();
        s.addColumn(Bytes.toBytes("myFamily"), Bytes.toBytes("someQualifier"));
        ResultScanner scanner = table.getScanner(s);
        try {
            for (Result rr : scanner) {
                System.out.println("Found row: " + rr);
            }
        } finally {
            scanner.close();
        }
    }
}

程式的內容, 在之後的文章中再說明.

接下來的問題是:
要如何編譯(compile)java程式, 並且執行呢?

在這支java程式中, 我們看到程式不只用了常見的java函式庫,
還引入了一系列 org.apache.hadoop.conf.與org.apache.hadoop.hbase.的函式,
因此, 在compile時, 必須指出這些函式的位置:

$ javac -cp /opt/hbase/*:/opt/hbase/conf/*:/opt/hadoop/conf/*:/opt/hbase/lib/* hbasetest.java

在這裡, javac -cp後面接的就是hadoop和hbase的函式,
不同位置間, 以冒號(:)分開, 最後接上要compile的java程式,
一般來說, 我們會放入hbase和hadoop的conf位置(/opt/hbase/conf/*,/opt/hadoop/conf/*),
hbase的引用的函式庫(/opt/hbase/lib/*)以及hbase本身的函式(/opt/hbase/*),
compile完畢產生hbasetest.class的檔案,
若是有缺少, 則compile時出現找不到函式的錯誤,
完成後, 封裝產生jar檔案:

$ jar -cvf hbasetest.jar hbasetest.class

在執行hbasetest.jar程式時, 必須使用hadoop/bin/hadoop jar來執行,
不過, 在此之前, 還要修改一下hadoop/conf/hadoop-env.sh,
告訴hadoop, hbase函式庫的位置, 因此, 我們在java home下面加入:

# The java implementation to use.  Required.
export JAVA_HOME=/usr/lib/jvm/java-6-oracle/
export HBASE_HOME=/opt/hbase/

# Extra Java CLASSPATH elements.  Optional.
export HADOOP_CLASSPATH=
$HBASE_HOME/conf/*:$HBASE_HOME/lib/*:$HBASE_HOME/*:HADOOP_CONF_DIR
export HADOOP_CONF_DIR=/opt/hadoop/conf

並且重新啟動hadoop與hbase叢集,
在完成設定後, 我們就可以用以下指令執行hbase-client的程式:

$ hadoop/bin/hadoop jar hbasetest.jar hbasetest

以下是執行的結果(忽略hbase的LOG):

GET: Some Value
Found row: keyvalues={myRow/myFamily:someQualifier/1426183687689/Put/vlen=10/mvcc=0}

[2016/05/21 更新]
若是有以下錯誤:
Exception in thread "main" java.lang.NoClassDefFoundError: com/google/protobuf/Message
at org.apache.hadoop.hbase.io.HbaseObjectWritable.(HbaseObjectWritable.java:263)
at org.apache.hadoop.hbase.ipc.Invocation.write(Invocation.java:139)
at org.apache.hadoop.hbase.ipc.HBaseClient$Connection.sendParam(HBaseClient.java:638)
at org.apache.hadoop.hbase.ipc.HBaseClient.call(HBaseClient.java:1001)
at org.apache.hadoop.hbase.ipc.WritableRpcEngine$Invoker.invoke(WritableRpcEngine.java:150)
at com.sun.proxy.$Proxy5.getProtocolVersion(Unknown Source)
at org.apache.hadoop.hbase.ipc.WritableRpcEngine.getProxy(WritableRpcEngine.java:183)
at org.apache.hadoop.hbase.ipc.HBaseRPC.getProxy(HBaseRPC.java:335)
at org.apache.hadoop.hbase.ipc.HBaseRPC.getProxy(HBaseRPC.java:312)
at org.apache.hadoop.hbase.ipc.HBaseRPC.getProxy(HBaseRPC.java:364)
at org.apache.hadoop.hbase.client.HConnectionManager$HConnectionImplementation.getMaster(HConnectionManager.java:682)
at org.apache.hadoop.hbase.client.HBaseAdmin.(HBaseAdmin.java:110)
at hbasetest.main(hbasetest.java:20)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.apache.hadoop.util.RunJar.main(RunJar.java:156)
Caused by: java.lang.ClassNotFoundException: com.google.protobuf.Message
at java.net.URLClassLoader$1.run(URLClassLoader.java:202)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
at java.lang.ClassLoader.loadClass(ClassLoader.java:306)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)
at java.lang.ClassLoader.loadClass(ClassLoader.java:247)
... 18 more
請把/opt/hbase/lib/protobuf-java-2.4.0a.jar
複製到/opt/hadoop/lib底下OK了!

留言

熱門文章

LTE筆記: RSRP, RSSI and RSRQ

[WiFi] WiFi 網路的識別: BSS, ESS, SSID, ESSID, BSSID

LTE筆記: 波束成型 (beamforming) 和天線陣列