S-JIS[2010-07-11] 変更履歴

HBase0.20にJavaからアクセスするサンプル

HBase0.20にJavaからアクセスする例。


ライブラリー

HBaseにアクセスするには、HBaseのjarファイルの他に、Hadoopのjarファイルが必要。[2010-02-20]
とは言っても、hbase-0.20.3では、HBaseの中に必要なHadoopのjarファイルが入っている。

  jarファイル 備考
HBase C:\cygwin\usr\local\hbase-0.20.3\hbase-0.20.3.jar ↓ソースの場所(Eclipseで添付可能)
C:/cygwin/usr/local/hbase-0.20.3/src/java
C:\cygwin\usr\local\hbase-0.20.3\lib\ commons-logging-1.0.4.jar  
zookeeper-3.2.2.jar 分散システムアクセスの何か
log4j-1.2.15.jar  
Hadoop C:\cygwin\usr\local\hbase-0.20.3\lib\ hadoop-0.20.1-hdfs127-core.jar Hadoop分散ファイルシステム

lib直下にはjarファイルがたくさんあるが、単独環境ではとりあえず上記の4つがあれば動くようだ。


HBaseアクセスのサンプル

まったく申し訳ない&ありがたいことに、豊月さんのサンプルほぼそのまんまです。[2010-02-20]

import org.apache.hadoop.fs.Path;
import org.apache.hadoop.hbase.HBaseConfiguration;
import org.apache.hadoop.hbase.client.Get;
import org.apache.hadoop.hbase.client.HTable;
import org.apache.hadoop.hbase.client.Result;
import org.apache.hadoop.hbase.util.Bytes;
public class HBaseSample {

	public static void main(String[] args) throws IOException {
		// 設定ファイルを指定
		HBaseConfiguration conf = new HBaseConfiguration();
		conf.addResource(new Path("C:/cygwin/usr/local/hbase-0.20.3/conf/hbase-site.xml"));

		// テーブルを指定(ここでHBaseへ接続)
		HTable table = new HTable(conf, Bytes.toBytes("TEST_TYPE"));
		try {
			// 取得したテーブルからROW(キー)を指定してデータを取得
			Get g = new Get(Bytes.toBytes("KEY00001"));
			Result r = table.get(g);

			// 項目ColumnFamilyAのデータを取得
			byte[] value = r.getValue(Bytes.toBytes("ColumnFamilyA"));
			String valueStr = Bytes.toString(value);

			System.out.println(valueStr);
		} finally {
			table.close();
		}
	}
}

org.apache.hadoop.hbase.util.Bytesは、UTF-8で文字列をバイト列に変換するユーティリティー。
したがって、UTF-8以外のエンコードを使いたい場合は自分でString#getBytes("MS932")とかを使う。
Bytesクラスのメソッド

HBaseのプログラムは、Eclipseから直接実行することが出来る。
Hadoopだとhadoopシェルから実行しないといけないが)


log4jの設定

上記のサンプルを動かしてみると、標準エラーにZooKeeperのログがぼろぼろ出てくる。[2010-02-20]
HBASE_HOME/conf/にlog4j.propertiesがあるが、これはデフォルトでは使われていない。
中身の出力レベルを変えてこのファイルを使うようにすればログ出力を制御できる。

C:/cygwin/usr/local/hbase-0.20.3/conf/log4j.properties:

# Define some default values that can be overridden by system properties
hbase.root.logger=WARN,console
hbase.log.dir=.
hbase.log.file=hbase.log
〜
#
# console
# Add "console" to rootlogger above if you want to use this 
#
log4j.appender.console=org.apache.log4j.ConsoleAppender
log4j.appender.console.target=System.err
log4j.appender.console.layout=org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern=%d{yyyy/MM/dd HH:mm:ss} %p %c{2}: %m%n

# Custom Logging levels

#log4j.logger.org.apache.zookeeper=INFO
#log4j.logger.org.apache.hadoop.fs.FSNamesystem=DEBUG
#log4j.logger.org.apache.hadoop.hbase=DEBUG
#log4j.logger.org.apache.hadoop.dfs=DEBUG

一番上のhbase.root.loggerがデフォルトの出力レベルで、元々INFOになっているのでWARNに変える。
一番下がパッケージ名ごとの出力レベルなので、コメントアウトする。
(あと、「年」は4桁で表示すべき!)

HBaseSample.java:

import org.apache.log4j.PropertyConfigurator;
public static void main(String[] args) throws Exception {
	// log4jの設定ファイルを指定
	PropertyConfigurator.configure("C:/cygwin/usr/local/hbase-0.20.3/conf/log4j.properties");

	// 設定ファイルを指定
	HBaseConfiguration conf = new HBaseConfiguration();
〜

PropertyConfiguratorでlog4jの設定ファイルを指定する。
ZooKeeperのクラスがロードされるより前(HBaseのテーブルにアクセスするより前)に設定すること。


HBaseのエラー

HBaseのプログラムの実行時に発生したエラー(例外)は、log4j.propertiesで指定した場所にエラーメッセージが出力される。[2010-02-20]

以下、各行の先頭に「WARN」や「DEBUG」と出ているのはlog4jの出力、それ以外は普通にコンソールに出力されたメッセージ(例外のスタックトレース)。


HBaseが起動していないので接続に失敗しているケース。

		HTable table = new HTable(conf, "TEST_TYPE");	←ここで発生
エラー(例外)の内容 備考
WARN zookeeper.ClientCnxn: Exception closing session 0x0 to sun.nio.ch.SelectionKeyImpl@f0eed6
java.net.ConnectException: Connection refused: no further information

WARN zookeeper.ClientCnxn: Ignoring exception during shutdown input
java.nio.channels.ClosedChannelException

WARN zookeeper.ClientCnxn: Ignoring exception during shutdown output
java.nio.channels.ClosedChannelException

WARN zookeeper.ZooKeeperWrapper: Failed to create /hbase -- check quorum servers, currently=127.0.0.1:2181
org.apache.zookeeper.KeeperException$ConnectionLossException: KeeperErrorCode = ConnectionLoss for /hbase
「127.0.0.1:2181」は、hbase-site.xmlの
hbase.zookeeper.quorum
hbase.zookeeper.property.clientPort
で指定したZooKeeperのアドレス。
DEBUG client.HConnectionManager$TableServers: Sleeping 1000ms, waiting for root region. 接続失敗時にリトライするまでちょっとスリープする。
「1000ms」は、hbase-site.xmlの
hbase.client.pause
で指定した時間。
DEBUG client.HConnectionManager$TableServers: locateRegionInMeta attempt 0 of 10 failed; retrying after sleep of 1000 because: Timed out trying to locate root region locateRegionInMeta()の失敗。
リトライ最大回数の「10」はhbase-site.xmlの
hbase.client.retries.number
で指定した回数だが、
「0 of 10」なので、初回の失敗。
Exception in thread "main" org.apache.hadoop.hbase.client.NoServerForRegionException: Timed out trying to locate root region

WARN zookeeper.ClientCnxn: Ignoring exception during shutdown input
java.nio.channels.ClosedChannelException

WARN zookeeper.ClientCnxn: Ignoring exception during shutdown output
java.nio.channels.ClosedChannelException

DEBUG zookeeper.ZooKeeperWrapper: Closed connection with ZooKeeper
locateRootRegion()の失敗。
ZooKeeperへの接続のリトライ回数オーバー。
リトライ回数はhbase-site.xmlの
hbase.client.retries.number
で指定した回数。

HConnectionManagerの各メソッド内でそれぞれリトライを行っているようなので、最終的に停止するまでの合計リトライ回数はhbase-site.xmlで指定したリトライ回数より多くなる。

対処方法としては、ZooKeeper(HBase)を起動する。


データ取得がタイムアウトしたケース。

		Result r = table.get(g);	←ここで発生
エラー(例外)の内容 備考
Exception in thread "main" org.apache.hadoop.hbase.client.RetriesExhaustedException: Trying to contact region server 192.168.xxx.1:1838 for region TEST_TYPE,,1266507739937, row 'KEY00001', but failed after 1 attempts.
Exceptions:
org.apache.hadoop.hbase.client.RetriesExhaustedException: Failed setting up proxy to /192.168.xxx.1:1838 after attempts=1
    at org.apache.hadoop.hbase.client.HConnectionManager$TableServers.getRegionServerWithRetries(HConnectionManager.java:1048)
    at org.apache.hadoop.hbase.client.HTable.get(HTable.java:417)
    at jp.hishidama.sample.hbase.HBaseSample.main(HBaseSample.java:33)
TEST_TYPEテーブルの
row=KEY00001から
データを取得しようとして
リトライオーバー。

接続が成功していてもデータアクセスにはちょっと時間がかかるので、待ち時間を越えてしまうことがある。

対処法としては、リトライ回数hbase.client.retries.numberを多くする。
(上の例は、リトライ回数2回で起きた。状態が良くなれば、リトライ回数1回でも発生しないけど)


その他分かりやすいケース。

エラー(例外)の内容 備考
Exception in thread "main" org.apache.hadoop.hbase.TableNotFoundException: TEST_TYPE2 TEST_TYPE2テーブルが存在しない。
  値の取得(Get)において、
ROWが存在しない場合
ColumnFamilyが存在しない場合
Columnが存在しない場合
はResult#getValue()でnullが返るだけで、エラーにはならない。

Java APIへ戻る / HBaseへ戻る / HBase変更点へ / Java目次へ行く / 技術メモへ戻る
メールの送信先:ひしだま