Log4j + syslog の設定

Log4j を syslog へ転送する時はファシリティと Syslog サーバが指定できる。log4j.xml の <appender> → <param> 指定は該当する Appender クラスのプロパティ名と同じなので、詳しくは API リファレンスの setter を参照。
SyslogAppender (Apache Log4j 1.2.17 API)

例えば

  • <param name="facility" value="local4"/> … ファシリティ local4 を使用
  • <param name="facilityPrinting" value="false"/> … ファシリティを出力しない
  • <param name="header" value="false"/> … タイムスタンプとホスト名を出力しない

など。

タグを指定するプロパティは存在しないが、これはケースバイケースで対応可能。

固定値で良い場合
PatternLayout 上で直接指定 ("[myapp] %m%n")
プロセスごとに変えたい場合
起動時のシステムプロパティで指定 ("[${syslog.tag}] %m%n"、起動オプションに -Dsyslog.tag=myapp 追加)
スレッドごとに変えたい場合
アプリケーションから NDC や MDC で指定 ("[%X{tag}] %m%n"、アプリ内でスレッド開始時に MDC.put("tag", "myapp"); 追加)
出力ごとに変えたい場合
アプリで出力するたびにフォーマット (logger.info("[" + myapp + "] ...") )

コードは通常の Log4j と変わらず。設定ファイルも概ね以下のようなイメージで構成できる。

import org.apache.log4j.*;
public class A{
  public static void main(String[] args){
    Logger logger = Logger.getLogger("org.koiroha.myapp");
    logger.info("hello, world");
    return;
  }
}
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
  <appender name="syslog" class="org.apache.log4j.net.SyslogAppender">
    <param name="threshold" value="info"/>
    <param name="syslogHost" value="localhost"/>
    <param name="facility" value="user"/>
    <layout class="org.apache.log4j.PatternLayout">
      <param name="conversionPattern" value="${org.koiroha.appname} %m%n"/>
    </layout>
  </appender>
  <root>
    <priority value ="info"/>
    <appender-ref ref="syslog"/>
  </root>
</log4j:configuration>
$ java -Dlog4j.configuration=log4j.xml -Dorg.koiroha.appname=sample1 A
2012-02-29 16:30:37,425  INFO myapp- [sample1] hello, world
$ java -Dlog4j.configuration=log4j.xml -Dorg.koiroha.appname=sample2 A
2012-02-29 16:30:41,633  INFO myapp- [sample2] hello, world

ただし 1024 バイト以上のメッセージとなる場合は 2 以上のパケットに分割されるため、2つめ以降にタグは付けられない。

HFile と Memstore のメモ

  • store files は HFile の事。
  • Key-Value 不変マップ。
  • HFile はブロックに分けられていて、最後にブロックインデックスが付属している。
  • ブロックインデックスは HFile がオープンされた時に読み込まれメモリ上に保持される。
  • デフォルトのブロックサイズは 64kB。
  • 更新データは最初 write-ahead log (WAL) と呼ばれるコミットログに書き込まれメモリ内の memstore に保存される。
  • データの大きさが許容量を超えたら HFile としてディスクにフラッシュされる。
  • フラッシュが終わるとコミットログ内の最新未フラッシュ更新まで破棄される。
  • memstore の内容をディスクにフラッシュしている間、読み込み/書き込み処理はブロックされない。
  • これは、既存のいっぱいになった領域がファイルに書きこまれている間に、新しく作成した空の領域を更新するよう、メモリ上の memstore をローリングすることでアーカイブされる。
  • memstore 上のデータはディスク上の HFile の内容と全く同じようにキーでソートされている。このため保存時に特にソートなどの処理は行われない。

protocol error: bad line length character と出たら

SSH 接続できるはずのサーバに git で接続できないと思ったら:

git clone ssh://git.myserver/git/hoge
Password:
fatal: protocol error: bad line length character: [31

SSH でのターミナル接続時に何かログインメッセージのようなものを表示していませんか? これが git-ssh 間のプロトコルに紛れて悪さをします。

YCSB で HBase のベンチマーク

YCSB (Yahoo! Cloud Serving Benchmark) はクラウドサービスで使用される様々なデータストアのベンチマークプログラム。Apache 2 ライセンスで配布されており HBase, BigTable, Cassandra, MongoDB, CouchDB, Dynomite, Redis などほとんどの NoSQL 系データストアに対応しています。

ただいま HBase の性能検証を行なっているので YCSB を使ってみます。

手順

ビルド

YCSB は実行形式での配布はされていないようなので github からソースを持ってきてビルドします。git, Java (6 で動いた), Apache Ant と HBase のライブラリが必要です。

torao@clove$ git clone git://github.com/brianfrankcooper/YCSB.git
torao@clove$ cd YCSB
torao@clove$ cp /usr/lib/hbase/hbase*.jar db/hbase/lib
torao@clove$ cp /usr/lib/hbase/lib/*.jar db/hbase/lib
torao@clove$ ant
torao@clove$ ant dbcompile-hbase
テーブル作成

HBase Shell からベンチマークで使用するテーブルを作成します。usertable は固定値で family 部分が実行時に変更可能です。

torao@clove$ hbase shell
HBase Shell; enter 'help<RETURN>' for list of supported commands.
Type "exit<RETURN>" to leave the HBase Shell
Version 0.90.4-cdh3u2, r, Thu Oct 13 20:32:26 PDT 2011
hbase(main):001:0> create 'usertable'.'family'
実行

リモートからの接続方法が分からず少々行き詰まる…。どうもこのツールは localhost 以外の接続先を選択する設定がない様子。ベンチマーク処理の負荷が加算されてしまうのが気になりますが、仕方が無いので ZooKeeper が動作しているノードで実行します。

torao@clove$ java -cp build/ycsb.jar:db/hbase/lib/* com.yahoo.ycsb.Client -load -db com.yahoo.ycsb.db.HBaseClient -P workloads/workloada -p columnfamily=family -p recordcount=1000000 -s > ycsb-load.log

まず -load オプションを指定して100万件のレコードを投入します。上記の操作で yscb-load.log には INSERT のベンチマークが保存されます。

torao@clove$ java -cp build/ycsb.jar:db/hbase/lib/* com.yahoo.ycsb.Client -t -db com.yahoo.ycsb.db.HBaseClient -P workloads/workloada -p columnfamily=family -p operationcount=1000000 -s > ycsb-test.log

次に -t オプションで100万オペレーションを実行します。yscb-test.log には UPDATE, READ のベンチマークが保存されます。-P オプションで指定したファイルは設定のデフォルト値と INSERT, UPDATE, READ, SCAN の負荷割合を定義しているので HBase の使用想定に合わせて選べば良いかと思います。

Workload A Update heavy workload
Workload B Read mostly workload
Workload C Read only
Workload D Read latest workload
Workload E Short ranges
Workload F Read-modify-write workload

その他、スレッド数や秒間実行回数の調整も行えますので java -cp build/ycsb.jar:db/hbase/lib/* com.yahoo.ycsb.Client の結果を参照して下さい。

結果

リダイレクトされたファイルにはオペレーションの最小、最大、平均、95%、99% 時間とミリ秒ごとのヒストグラムが出力されます (us は μsec の意味)。

YCSB Client 0.1
Command line: -t -db com.yahoo.ycsb.db.HBaseClient -P workloads/workloada -p columnfamily=family -p operationcount=1000000 -s -threads 10
[OVERALL], RunTime(ms), 83851.0
[OVERALL], Throughput(ops/sec), 11925.91620851272
[UPDATE], Operations, 499992
[UPDATE], AverageLatency(us), 434.1214899438391
[UPDATE], MinLatency(us), 1
[UPDATE], MaxLatency(us), 12981941
[UPDATE], 95thPercentileLatency(ms), 0
[UPDATE], 99thPercentileLatency(ms), 0
[UPDATE], Return=0, 499992
[UPDATE], 0, 499962
[UPDATE], 1, 0
[UPDATE], 2, 0
[UPDATE], 3, 0
…

MagicCube レーザーキーボードを使ってみた

個人的に iPod touch + WiMAX が携帯には最強なのだが、キーボード並の入力能力があれば Blog 書きやミーティング、プレゼンなどのメモ書きにわざわざ ThinkPad を持ち歩く必要もなくなるだろう。そんなわけで、迷ったら買わない主義の吾輩が迷わず買った celluon の Matic Cube Bluetooth レーザーキーボードを持ち出してみました。

今時の PC 周辺機器ではありえないようなコストパフォーマンス無視の透明アクリルハードケースに入っている。箱書きも説明書も全て英語である (公式サイトに日本語説明書の PDF がある)。
かさばらない Bluetooth キーボードを探していました。あまり頻繁に使うものでもない

どうですかこのサイバー感。スタバで MacBook Air な連中が昭和かと思えるほどの存在感です。

Bluetooth ペアリングのコード入力をどうすればよいのかしばらく迷ったが、キーボードなんだからそのまま入力すれば良かった。

タイピング音量調整 [Fn] + [↑] で Up、[Fn] + [↓] で Down、最下はミュート
レーザー輝度調整 [Fn] + [→] で Up、[Fn] + [←] で Down
感度調整 [Fn] + [<] で Up、[Fn] + [>] で Down
マウスモード切替 [Fn] + [CURSOR] でマウスモード、[CURSOR] でキーボードモード
日本語入力切替 (iOS) [Menu] + [SPACE] でトグル

Android での日本語入力切替方法は分かりませんでした。

  • スタバで MacBook Air な連中が大正時代かと思えるほどのサイバー感。
  • 接続が今時ミニ USB なのでスマートフォン等とケーブルの使い回しができない。
  • バッテリー持続 2.5 時間はファミレスなどでじっくり文章を書くには少し短いかな。
  • ホームポジションが確定しないのでブラインドタッチは無理か。
  • 駆動部品がない = 故障が少ないという期待感。

OutOfMemory でスレッドの起動に失敗する件

十分なメモリを割り当てているにもかかわらず Hadoop や Thrift ゲートウェイで OutOfMemoryError が発生しスレッド生成に失敗する事案。

2012-01-18 19:54:16,620 ERROR org.apache.hadoop.hdfs.server.datanode.DataNode: DatanodeRegistration(192.168.121.93:50010, storageID=DS-1008921043-xxx.xxx.xxx.xxx-xxxxxx-xxxxxxxxxxxxxxx, infoPort=50075, ipcPort=50020):DataXceiverServer: Exiting due to:java.lang.OutOfMemoryError: unable to create new native thread
        at java.lang.Thread.start0(Native Method)
        at java.lang.Thread.start(Thread.java:640)
        at org.apache.hadoop.hdfs.server.datanode.DataXceiverServer.run(DataXceiverServer.java:131)
        at java.lang.Thread.run(Thread.java:662)

2012-01-18 19:54:16,620 INFO org.apache.hadoop.hdfs.server.datanode.DataNode: PacketResponder 0 for block blk_5441514272352034349_78759 terminating
2012-01-18 19:54:16,620 INFO org.apache.hadoop.hdfs.server.datanode.DataNode: Exiting DataXceiverServer
2012-01-18 19:54:16,623 INFO org.apache.hadoop.hdfs.server.datanode.DataNode: PacketResponder 0 for block blk_4867391491560614348_78761 terminating
2012-01-18 19:54:16,624 INFO org.apache.hadoop.hdfs.server.datanode.DataNode: Deleted block blk_6316283104492897854_78701 at file /var/lib/hadoop/dfs/data/sdb1/current/blk_6316283104492897854
…

GC 時に出力される空きメモリ量は余裕があるし、OS に割り当てているメモリ量も該当 Java VM のネイティブ使用量コミで十分収まる見積もりなのに何故? と悩んでいましたが、単に ulimit で設定している起動プロセス数の上限に達したというオチでした。まぁ HadoopJava VM に限った話ではなかったですが。

torao@clove$ ulimit -a
…
max user processes              (-u) 1024

Hadoop のデータノードで起きると自動的にシャットダウンしようとして七転八倒するし、Thrift でも通信不能の接続が残ってしまってプロセス再起動が必要と後始末が大変。