たごもりすメモ

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

Hoop(httpfs)とwebhdfsの違い

Hadoop 1.0.0リリースされた。まあ中身のほとんどはただの 0.20.x 安定板リリースなので特別に言うことはないんだけど。詳しくは以下のblogを読むのがよろしい。

hadoopのバージョン表記について - 科学と非科学の迷宮

ただしひとつだけびっくりしたのは、webhdfsなる機能が入ってきたこと。(このblogでよく話題にしている)Hoopと並んでそんなようなものがあること自体は知ってたけどあんまり興味なかったのだが、Apache Hadoopのパッケージに(Hoopより先に)入ったとなるとちょっと注目せざるをえない。
が、httpfs(Hoop)とwebhdfsじゃ名前も似てて超まぎらわしい。いったい何がなんなの。

なお自分はWebHDFSはAPIリファレンスを読んだだけで、実際にはカケラも触っていない。その状況での理解による内容なので、注意して読んでください。

先に結論だけ書く

どちらもクライアントからはHTTP REST APIで叩く。可能なオペレーションの幅も同じ。認証もユーザ名ベースの仮認証(pseudo auth)かKerberosのどちらか。ただしサーバ側をどのノードが担当するかという点、およびHTTPの通信パターンが異なる。
ぶっちゃけて言うと、これまでJava実装のHDFSClientがやっていた通信をHTTP REST APIで置き換え可能にする、というものがWebHDFSだと言っていい。

このため、機能的にはほぼ同じだが、性能特性はいくらか異なることが考えられる。どのようなアクセスパターンでどちらが良いかという確定的なことはまだ言えない。ぶっちゃけだいぶ実装による。ので、実際に試すしかないと思う。クライアントの実装がたぶん重要。
あと安定性にも違いが出るかもしれない。webhdfsのHTTPサーバ部分の実装がhdfsコアと同じ完成度なのかどうか、という点が重要。ここの完成度が高いならwebhdfsも安定するだろう。Hoop(httpfs)は今のところ安定性の面で問題を見付けたことはない。

Hoop(httpfs)の構造

Hoop Serverを立てる場合の構造および通信パターンとプロトコルをざっくり図示すると、こんな感じ。

クライアントは全ての操作について、Hoop Serverに対してHTTP REST APIでリクエストを投げる。Hoop Serverはリクエストを受け取ったら、それに対応するHDFSアクセス操作をJava実装のHDFSClient経由でHadoopクラスタに対して行い、結果をクライアントに戻す。

構造は単純だ。Hoop ServerはただのプロキシサーバでHDFS側から見ると普通のクライアントアプリケーションなので、ぶっちゃけ我々でも書こうと思えば書ける。

WebHDFSの構造

対してWebHDFSの場合、ノード間の関係および通信パターンはこんな感じ。

つまり、全てのNameNodeとDataNodeがHTTPをしゃべる。いっぽうプロキシサーバ的なものは存在せず、HDFSClientが各ノードと行っていたような通信を、そのかわりにHTTPを使って行うこととなる。HDFSClientの実装に依存するしかなかったクラスタとの直接通信をHTTPで代替できるようになったということだ。

いっぽう面倒くさい部分がある。周知の通りHDFSはディレクトリ構造およびファイルのメタデータをNameNodeが、ファイル実体をDataNodeが管理している。このため、ディレクトリ構造やファイルのメタデータに関する操作ならNameNodeにリクエストを投げてレスポンスを見ればいいのだが、ファイルの内容に関する操作(ファイル作成・追記、ファイルの内容取得)については、以下のような手順を踏む必要がある。

  1. NameNodeのリクエストを送信
  2. NameNodeのレスポンスによりDataNodeのどれかにリダイレクトされる
  3. DataNodeにリクエストを送信
  4. DataNodeから結果が返ってくる

上記のように一回のHTTPリクエストで処理が完結しない。これはクライアントの実装を行う上ですこし面倒だし、性能面でも影響を与える可能性がある。*1
いっぽう間にプロキシを挟まないためDataNodeと直接通信をする部分においてはスループットがかなり出ることも予想され、その面ではパフォーマンスに関する期待は持てる。つまりは結局アクセスパターン次第ですね、ということになるかもしれない。

なおHTTPリクエストのパターンが面倒なのは、将来的には解決される可能性がある。本来ならレスポンスとして 'Expect: 100 Continue' を使って直接DataNodeに処理を引き継ぐようにしたいらしい。現状でNameNodeのレスポンスがDataNodeへのリダイレクトになっているのはJettyのバグのせいであるとREST APIに明言されている。
これが解決されたら、クライアント側で2回のHTTPリクエストをハンドリングする必要がなくなるかもしれない*2。ただし、性能特性としては変わらないままだろう。

雑感

NameNodeおよびDataNodeへの直接の通信は、これまでJava実装によるHDFSClientに頼るしかない状況だった。これがHTTP REST APIという平易なもので置き換え可能になったという点で、WebHDFSの存在意義は大きいと思う。つまり誰でも各言語ネイティブのHDFSクライアントライブラリが書けるようになったということだ。
WebHDFSのREST APIリファレンスはだいぶしっかりした作り*3になっていて、仕様的にちゃんと考えられているんだなあ、という気もする。レスポンスJSONスキーマなんかもちゃんと書かれているのでだいぶ実装にあたっての心理的障壁は低い*4。このAPIの互換性がしっかりと守られるなら、もしかしてJava実装のHDFSClientベースでクライアントライブラリを使うよりもWebHDFSベースでクライアントライブラリを書いてしまった方がバージョン互換性が保たれるということにもなりそうだ。

とはいえ、全てのクライアントアプリケーションがNameNodeおよびDataNodeのすべてと相互に通信するというのはなかなか面倒だし、トラブル時に何をどう考えればいいのかも複雑になる。なので、通信パターンの単純化、ということだけ考えてもhttpfs(Hoop)の存在意義はある。実際の運用を考えるとこの面はあまり軽視したものでもない。

ということで最後にはいつもの通りだが、用途とアクセスパターン、運用状況にあわせて適宜選択するのがよろしいでしょう。ああ、誰かHadoop 1.0.0のWebHDFS実装でベンチマークをとってくれないか・・・!

おまけ

ふと考えたんだが、HTTP REST APIでクライアントのリクエストを受け取ってWebHDFSでHadoopクラスタに処理を投げるプロキシサーバがあると、実は一番良いんじゃなかろうか。本当かな。

*1:前半のNameNodeからのレスポンスをキャッシュできるのかどうか、できるとしたらどの条件下でキャッシュできるのか、が明らかになれば少し違うかもしれない。

*2:HTTPクライアントライブラリが処理を裏側でやってくれるなら。

*3:ただしPDFのみ。なぜ……。

*4:この点Hoopはだいぶダメダメ。。。