たごもりすメモ

コードとかその他の話とか。

HiveServerを使う上での注意点

というか、えー、問題にハマりましたので。問題が炸裂した夜はわたくし渋谷で飲んでおりまして、対応と原因のアタリをとっていただきました同僚の方々にはお礼の言葉しかございません。

ThriftHiveプロトコルにおけるcleanメソッド

まず第一に、HiveServerに対してThrift経由で接続(ThriftHiveを使用)する場合、以下の点に注意する必要がある、というのが大前提です。

  • クライアントはクエリ結果の読み出しを含む全処理が終わったあとに clean() を呼んでから通信を切断すること
    • これが行われないとHiveServerはクエリの処理に使用したファイルディスクリプタや一時ファイルの類をすべて保持したままにする
    • cleanを自動的にやってくれるような機構は存在しない
  • cleanメソッドは比較的最近のバージョンのHiveにしか存在しない
    • 少なくとも自分が最初にshibを作ったとき(CDH3b2がターゲット)は存在しなかった
    • CDH3u2では存在したので、その間のどこか(に対応するHiveのどれかのバージョン)で取り込まれた

cleanを呼ばないとHiveServerが開いているファイルディスクリプタは増え続け、ulimitで設定した値を超えたところで一切の接続要求に応答しなくなってスタックします。こうなったら再起動するしか手がありませんから注意しましょう。

しかしクライアントの作り方を間違えるとサーバが死亡するってだいぶひどいですね。というか、そもそもcleanメソッドなかった期間がだいぶ長かったはずだけどその間どうしてたんだ。
まあHiveServer2とやらがそのうち出てくるらしいのでそれに期待すればいいんじゃないでしょうか。

HiveServerにおけるファイルディスクリプタの扱い

上記の点に注意してクライアントのコードを書き換えても、Hiveクエリ実行後にやっぱりファイルディスクリプタがふたつ開かれたままの状態になってしまい、あれーやっぱりリークしてねー? と思ってtwitterぎゃーと騒いでたら親切なタムタムさんが調べてくれた*1

で、結論としてはGCがきちんと走れば結果的にはリークしないで済む、ようですね! GCにfdのcloseを頼るのは個人的にはどうかと思うけど、問題ないんならまあ使う分にはいいや。

ちなみに、結論が出る前にHiveServerのopenしているファイルディスクリプタ数でも監視するかーと仕掛けておいたグラフがこちらになります。GrowthForecastまじべんり。

大丈夫そうですね!

*1:というか、自分でもだいたいコードは読んだんだけどまとめる気力がなかった……。

CDH4+YARN+Hiveでハマってる

検証用として新規にセットアップしたCDH4クラスタ、YARN使用で設定してみたんだけど以下のような状態。完全分散モード。

  • CDH4はtarballを展開する形でインストール
  • YARNで hadoop-mapreduce-example.jar は走る
    • ResourceManagerと同ホストから以下のコマンドを実行したら成功する
hadoop jar /usr/local/hadoop/share/hadoop/mapreduce/hadoop-mapreduce-examples-0.23.1-cdh4.0.0b2.jar pi 4 1000
  • HiveでMapReduceを介さない処理は成功する
    • 具体的にはSHOW TABLESやCREATE TABLEおよびLOADなど
  • HiveでSELECTすると、エラーになって失敗する
    • ResourceManagerのアプリケーション一覧にジョブが登録される
    • が以下のようなログが出て KILLED になる
2012-06-25 16:18:46,425 FATAL [IPC Server handler 5 on 16040] org.apache.hadoop.mapred.TaskAttemptListenerImpl:
    Task: attempt_1340595366899_0003_m_000002_0 - exited : java.lang.RuntimeException: java.io.FileNotFoundException:
     /tmp/USERNAME/hive_2012-06-25_16-18-34_931_2832351455751959226/-mr-10001/c2a2caf9-8bda-4e22-a3c2-4745531a927a (No such file or directory)
	at org.apache.hadoop.hive.ql.exec.Utilities.getMapRedWork(Utilities.java:223)
	at org.apache.hadoop.hive.ql.io.HiveInputFormat.init(HiveInputFormat.java:255)
	at org.apache.hadoop.hive.ql.io.HiveInputFormat.pushProjectionsAndFilters(HiveInputFormat.java:381)
	at org.apache.hadoop.hive.ql.io.HiveInputFormat.pushProjectionsAndFilters(HiveInputFormat.java:374)
	at org.apache.hadoop.hive.ql.io.CombineHiveInputFormat.getRecordReader(CombineHiveInputFormat.java:536)
	at org.apache.hadoop.mapred.MapTask$TrackedRecordReader.(MapTask.java:160)
	at org.apache.hadoop.mapred.MapTask.runOldMapper(MapTask.java:381)
	at org.apache.hadoop.mapred.MapTask.run(MapTask.java:334)
	at org.apache.hadoop.mapred.YarnChild$2.run(YarnChild.java:148)
	at java.security.AccessController.doPrivileged(Native Method)
	at javax.security.auth.Subject.doAs(Subject.java:396)
	at org.apache.hadoop.security.UserGroupInformation.doAs(UserGroupInformation.java:1177)
	at org.apache.hadoop.mapred.YarnChild.main(YarnChild.java:143)
Caused by: java.io.FileNotFoundException: /tmp/USERNAME/hive_2012-06-25_16-18-34_931_2832351455751959226/-mr-10001/c2a2caf9-8bda-4e22-a3c2-4745531a927a (No such file or directory)
	at java.io.FileInputStream.open(Native Method)
	at java.io.FileInputStream.(FileInputStream.java:120)
	at java.io.FileInputStream.(FileInputStream.java:79)
	at org.apache.hadoop.hive.ql.exec.Utilities.getMapRedWork(Utilities.java:214)
	... 12 more

Hive側でHDFSにputしたジョブ用のファイルをTaskTracker……じゃなくてNodeManager? 側から見えてないっぽい。なんでだ。もちろんslave側のノードでも hdfs dfs -ls とかすればちゃんとHDFS内のファイルは見えているんだけどなー。わからん。わからーん。

とりあえずそれだけ。なんか分かったら書く。

解決した! (7/3追記)

”Does not contain a valid host:port authority: local”がなんやねんという感じでいろいろ調べてみると、hive-site.xmlにJobTrackerのURLを指定する必要があるっぽかったので、指定しました。

CDH4 YARNでHive - marblejediary

これだ! これでした! HiveServerに全く同じログが出ていたのを間抜けにも見逃しておりました。NodeManager側で出ているログの結果こうなるのかなー、みたいななんとなくのヌルい思考でなんとなくスルーしてた!

ということで(YARN用の) hadoop.conf.dir と、あと mapred.job.tracker になんとなくResourceManagerをやっているホストのホスト名を書いたらHiveクエリでMapReduceが走って結果が返ってくるようになりました。万歳! @marblejenka++

ところでこっちでも java.lang.InterruptedException というのは出てますね。なんだろこれ……。