S-JIS[2012-10-02/2012-10-11] 変更履歴

WebHDFS REST API

WebHDFSのコマンド(REST API)のメモ。


使い方

REST APIなので、コマンド(URI)をブラウザーのURL欄に入力したり、wgetcurlコマンドを使うことで実行する。

$ wget "http://ネームノード:50070/webhdfs/v1〜"
$ curl "http://ネームノード:50070/webhdfs/v1〜"

接続先のサーバーはNameNode、ポート番号はHDFSのポート(CDH3のデフォルトなら50070、EMRなら9101)。
(ブラウザーから「/webhdfs/v1」を付けずにhttp://ネームノード:50070」にアクセスするとHDFSの状態を見られる画面が開くが、そのポート番号と同じ)

wgetを使うとファイルが作られる。
URIを元にファイル名が決まるので、ファイル名に「?」や「&」が含まれてしまう。「-O」オプションで出力ファイル名を指定した方が良さそう。

curlだとボディー部のみが画面に出力される。
「-i」オプションを付けるとヘッダー情報も表示される。
また、APIによってはHTTPのGETメソッドでなくPUTやDELETEを使うことがある。curlなら「-X」で指定できる。


URIに「http://ネームノード:50070/webhdfs/v1」だけ指定すると、以下のようなメッセージが返ってくる。

HTTP/1.1 400 Bad Request
Content-Type: application/json
Transfer-Encoding: chunked
Server: Jetty(6.1.26.cloudera.1)

{"RemoteException":{"exception":"UnsupportedOperationException","javaClassName":"java.lang.UnsupportedOperationException","message":"op=NULL is not supported"}}[

WebHDFSのAPIでは「op=命令」でどのような操作をするのか指定する必要がある。

認識できない命令を指定すると、以下のようなエラーになる。

"http://ネームノード:50070/webhdfs/v1?op=gethomedir"
↓
{"RemoteException":{"exception":"IllegalArgumentException","javaClassName":"java.lang.IllegalArgumentException","message":"Invalid value for webhdfs parameter \"op\": No enum const class org.apache.hadoop.hdfs.web.resources.GetOpParam$Op.GETHOMEDIR"}}

REST API

APIのコマンド(「op=」で指定するもの)は、大文字でも小文字でも大丈夫なようだ。
コマンドによってはオプション(引数)があるので、WebHDFS REST APIを参照。

コマンドの実行結果はJSON形式で返ってくる。

主な操作
操作 HTTP 返り値 hadoop相当
GETHOMEDIRECTORY
ホームディレクトリー取得
GET curl "http://namenode:50070/webhdfs/v1?op=gethomedirectory&user.name=hishidama" {"Path":"/user/hishidama"}  
LISTSTATUS
ファイル一覧取得
GET curl "http://namenode:50070/webhdfs/v1/user/hishidama?op=liststatus" ファイル・ディレクトリー情報の一覧
pathSuffixがファイルやディレクトリー名
hadoop fs -ls /user/hishidama
GETFILESTATUS
ファイル情報取得
GET curl "http://namenode:50070/webhdfs/v1/user/hishidama/test.txt?op=getfilestatus" ファイル情報 hadoop fs -ls /user/hishidama/test.txt
OPEN
ファイル読み込み
GET curl -i "http://namenode:50070/webhdfs/v1/user/hishidama/test.txt?op=open"
curl "http://データノード:50075/webhdfs/v1/user/hishidama/test.txt?op=OPEN&offset=0"
ファイルの内容 hadoop fs -cat /user/hishidama/test.txt
curl -L "http://namenode:50070/webhdfs/v1/user/hishidama/test.txt?op=open"
CREATE
ファイル作成
PUT curl -i -X PUT "http://namenode:50070/webhdfs/v1/user/hishidama/aaa.txt?op=create"
curl -i -X PUT "http://データノード:50075/webhdfs/v1/user/hishidama/aaa.txt?op=CREATE&overwrite=false" -T a.txt
JSONオブジェクトは無し hadoop fs -put a.txt /user/hishidama/aaa.txt
curl -i -X PUT -L "http://namenode:50070/webhdfs/v1/user/hishidama/aaa.txt?op=create" -T a.txt
MKDIRS
ディレクトリー作成
PUT curl -X PUT "http://namenode:50070/webhdfs/v1/user/hishidama/zzz?op=mkdirs" {"boolean":true}
ディレクトリーが既存でもtrueが返る
hadoop fs -mkdir /user/hishidama/zzz
RENAME
改名
PUT curl -X PUT "http://namenode:50070/webhdfs/v1/user/hishidama/zzz?op=rename&destination=/user/hishidama/zzz2" {"boolean":true}
対象が無い場合はfalse
hadoop fs -mv /user/hishidama/zzz /user/hishidama/zzz2
DELETE
削除
DELETE curl -X DELETE "http://namenode:50070/webhdfs/v1/user/hishidama/test.txt?op=delete" {"boolean":true} hadoop fs -rm /user/hishidama/test.txt
curl -X DELETE "http://namenode:50070/webhdfs/v1/user/hishidama/zzz2?op=delete&recursive=true" {"boolean":true} hadoop fs -rmr /user/hishidama/zzz2

WebHDFSとHttpFSの違い

HttpFSはWebHDFSにAPI(URIの形式)を合わせている。
しかし、URIはほぼそっくり同じだが、実際の動作は異なる部分があるので要注意。

CDH3u5版でのWebHDFSとHttpFSのAPIの相違点
操作   コマンド(API) 返り値 説明
LISTSTATUS
ファイル一覧取得
WebHDFS curl "http://namenode:50070/webhdfs/v1/user/hishidama/a.txt?op=liststatus" ファイル・ディレクトリー情報の一覧
pathSuffixがファイルやディレクトリー名
存在しているファイル名を指定した場合、
HttpFSはpathSuffixにファイル名が入るが、
WebHDFSは空文字列になる。
HttpFS curl "http://namenode:14000/webhdfs/v1/user/hishidama/a.txt?op=liststatus"
OPEN
ファイル読み込み
WebHDFS curl -i "http://namenode:50070/webhdfs/v1/user/hishidama/a.txt?op=open" HTTP/1.1 307 TEMPORARY_REDIRECT
Location: http://datanode02:50075/webhdfs/v1/user/hishidama/a.txt?op=OPEN&offset=0
Content-Type: application/octet-stream
Content-Length: 0
Server: Jetty(6.1.26.cloudera.1)
WebHDFSでは、NameNodeに対してオープンしたいファイル名を指定すると、DataNodeのURIが返ってくる。
そのURIを再度指定するとファイルの内容が返ってくる。

これはHTTPのリダイレクト処理なので、ブラウザーで1つ目のURIを指定すれば自動的にファイルがダウンロードされる。
curl -i "http://datanode02:50075/webhdfs/v1/user/hishidama/a.txt?op=OPEN&offset=0" ファイルの内容
HttpFS curl -i "http://namenode:14000/webhdfs/v1/user/hishidama/a.txt?op=open" ファイルの内容 HttpFSでは、最初のURIだけでファイルの内容が返ってくる。
CREATE
ファイル作成
WebHDFS curl -i -X PUT "http://namenode:50070/webhdfs/v1/user/hishidama/a.txt?op=create&user.name=hishidama" HTTP/1.1 307 TEMPORARY_REDIRECT
Location: http://datanode02:50075/webhdfs/v1/user/hishidama/a.txt?op=CREATE&user.name=hishidama&overwrite=false
Content-Type: application/octet-stream
Content-Length: 0
Server: Jetty(6.1.26.cloudera.1)
WebHDFSでは、NameNodeに対して作成したいファイル名を指定すると、DataNodeのURIが返ってくる。
そのURIを(転送したいファイル名と共に)再度指定するとデータが転送される。

HDFS上で2ブロック以上になる大きなファイルでも、リダイレクトは1回しか必要ないようだ。
「user.name」で指定したユーザー名がHDFS上のファイルのオーナーとなる。
指定しないと「webuser」になる。
curl -i -X PUT "http://datanode02:50075/webhdfs/v1/user/hishidama/a.txt?op=CREATE&user.name=hishidama&overwrite=false" -T a.txt HTTP/1.1 100 Continue

HTTP/1.1 201 Created
Location: webhdfs://namenode:50070/user/hishidama/a.txt
Content-Type: application/octet-stream
Content-Length: 0
Server: Jetty(6.1.26.cloudera.1)
HttpFS curl -i -X PUT "http://namenode:14000/webhdfs/v1/user/hishidama/a.txt?op=create&user.name=hishidama" HTTP/1.1 307 Temporary Redirect
Server: Apache-Coyote/1.1
Set-Cookie: hadoop.auth="u=hishidama&p=hishidama&t=simple&e=1349221868352&s=Fu+〜I="; Version=1; Path=/
Location: http://namenode:14000/webhdfs/v1/user/hishidama/a.txt?op=CREATE&user.name=hishidama&data=true
Content-Type: application/json
Content-Length: 0
Date: Tue, 02 Oct 2012 13:51:08 GMT
HttpFSでもHttpFSサーバー(今回はNameNodeと同一)に対して作成したいファイル名を指定するとURIが返ってくるのだが、DataNodeではなく、HttpFSサーバーのまま。ただし末尾に「data=true」が付いている。
このURIと共にファイル名を指定するとデータが転送される。
(最初から「data=true」を付けていれば、1回の呼び出しでファイルが作成できるようだ)
また、HTTPヘッダーでcontent-typeを明示しないとエラーになる。
curl -i -X PUT "http://namenode:14000/webhdfs/v1/user/hishidama/a.txt?op=CREATE&user.name=hishidama&data=true" -T a.txt --header "content-type: application/octet-stream" HTTP/1.1 100 Continue

HTTP/1.1 201 Created
Server: Apache-Coyote/1.1
Set-Cookie: hadoop.auth="u=hishidama&p=hishidama&t=simple&e=1349221981404&s=OFH〜8="; Version=1; Path=/
Content-Type: application/json
Content-Length: 0
Date: Tue, 02 Oct 2012 13:53:01 GMT
RENAME
改名
WebHDFS curl -i -X PUT "http://namenode:50070/webhdfs/v1/user/hishidama/z1?op=rename&destination=x1" HTTP/1.1 400 Bad Request
{"RemoteException":{
 "exception":"IllegalArgumentException",
 "javaClassName":"java.lang.IllegalArgumentException",
 "message":"Invalid value for webhdfs parameter \"destination\": Invalid parameter value: destination = \"x1\" is not an absolute path."
}}
destination(移動先名)に相対パスを指定するとエラーになるのだが、
WebHDFSでは400 Bad Requestでエラーメッセージが返るが、
HttpFSでは200 OKでfalseが返る。
HttpFS curl -i -X PUT "http://namenode:14000/webhdfs/v1/user/hishidama/z2?op=rename&destination=x2" HTTP/1.1 200 OK
{"boolean":false}
DELETE
削除
WebHDFS curl -i -X DELETE "http://namenode:50070/webhdfs/v1/user/hishidama/x1?op=delete" HTTP/1.1 403 Forbidden
{"RemoteException":{
 "exception":"IOException",
 "javaClassName":"java.io.IOException",
 "message":"/user/hishidama/x1 is non empty"
}}
空でないディレクトリーをrecursive=trueの指定無しで削除しようとするとエラーになるのだが、
WebHDFSは403 Forbiddenで、
HttpFSは500 Internal Server Errorになる。
HttpFSは単なるプロキシーなので、HDFS側で例外が発生したら(RemoteExceptionを受け取ったら)内部エラーとするしかない、ということか?
HttpFS curl -i -X DELETE "http://namenode:14000/webhdfs/v1/user/hishidama/x2?op=delete" HTTP/1.1 500 Internal Server Error
{"RemoteException":{
 "message":"java.io.IOException: \/user\/hishidama\/x2 is non empty",
 "exception":"RemoteException",
 "javaClassName":"org.apache.hadoop.ipc.RemoteException"
}}

curlコマンドについて

WebHDFSを試すにはcurlコマンドが便利。[2012-10-11]

-X

「-X」でHTTPメソッドを指定できる。
WebHDFSのREST APIではHTTPメソッドのGET以外をよく使用する。

-i・-I

「-i」でHTTPレスポンスのヘッダー部およびボディー部の内容を表示する。
「-I」だとヘッダー部のみ表示する。

ヘッダーの情報表示は、HTTPレスポンスの内容を(改行コードまで含めて)そのまま出しているような気がする。
HTTPでは改行はCRLF(0d0a)なので、UNIXではLF(0a)のみだから、場合によってはCR(0d)が悪さをするので要注意。
(例えばリダイレクト先のURIは「Location:」の行で分かるが、行末はCRLFになっているので、シェルのパイプとかでそのまま次のcurlコマンドの引数にしたりすると、CRが残っていて存在しないURIを指している状態になってしまう!)

-o 出力ファイル名

「-o」で出力ファイル名を指定できる。

-L

WebHDFSのOPENCREATEではリダイレクト先URIが返ってくるが、「-L」を付けておけば自動的にリダイレクトしてくれる。

curl -i -X PUT -L "http://namenode:50070/webhdfs/v1/user/hishidama/aaa.txt?op=create" 
		-T a.txt

WebHDFSへ戻る / Hadoopへ戻る / 技術メモへ戻る
メールの送信先:ひしだま