🌐

WebHDFSのファイル作成とHadoop HA

2021/11/06に公開

ドキュメントに(多分)書いていない挙動を見つけたのでメモです。

tl;dr

  • WebHDFSのファイル作成(op=CREATE)は、StandbyのNameNodeにもリクエストできるよ
  • ファイル読み取り(op=OPEN)や一覧(op=LISTSTATUS)はActiveにリクエストする必要があるよ

WebHDFSとは

HDFSに対し、REST(-ful)なAPIでアクセスするインターフェイスです。

HAとは

https://hadoop.apache.org/docs/stable/hadoop-project-dist/hadoop-hdfs/HDFSHighAvailabilityWithNFS.html

HA時のWebHDFSの挙動

AWS EMR(emr-6.4.0、Hadoop 3.2.1)を「複数のマスターノード」で起動し、試してみました。

他の操作

ファイル読み取り(等)はActiveに投げる必要があります。

アクティブに投げた時

curl "http://[アクティブNameNode]:9870/webhdfs/v1/?op=LISTSTATUS"
{"FileStatuses":{"FileStatus":[
{"accessTime":0,"blockSize":0,"childrenNum":1,"fileId":16386,"group":"hdfsadmingroup","length":0,"modificationTime":1636195142276,"owner":"hdfs","pathSuffix":"apps","permission":"755","replication":0,"storagePolicy":0,"type":"DIRECTORY"},
{"accessTime":0,"blockSize":0,"childrenNum":2,"fileId":16388,"group":"hdfsadmingroup","length":0,"modificationTime":1636195142452,"owner":"hdfs","pathSuffix":"tmp","permission":"1777","replication":0,"storagePolicy":0,"type":"DIRECTORY"},
{"accessTime":0,"blockSize":0,"childrenNum":3,"fileId":16395,"group":"hdfsadmingroup","length":0,"modificationTime":1636195142536,"owner":"hdfs","pathSuffix":"user","permission":"755","replication":0,"storagePolicy":0,"type":"DIRECTORY"},
{"accessTime":0,"blockSize":0,"childrenNum":1,"fileId":16399,"group":"hdfsadmingroup","length":0,"modificationTime":1636195142549,"owner":"hdfs","pathSuffix":"var","permission":"755","replication":0,"storagePolicy":0,"type":"DIRECTORY"}
]}}

スタンドバイに投げた時

 curl "http://[スタンドバイNameNode]:9870/webhdfs/v1/?op=LISTSTATUS"
{"RemoteException":{"exception":"StandbyException","javaClassName":"org.apache.hadoop.ipc.StandbyException","message":"Operation category READ is not supported in state standby. Visit https://s.apache.org/sbnn-error"}}

ファイル作成(op=create)

ファイル作成はStandbyに投げても受理されます。

curl -v -X PUT -L "http://[スタンドバイNameNode]:9870/webhdfs/v1/tmp/webhdfs_test_file?op=CREATE" -t test_file
*   Trying 172.31.0.41:9870...
* Connected to [スタンドバイNameNode] (172.31.0.41) port 9870 (#0)
> PUT /webhdfs/v1/tmp/webhdfs_test_file?op=CREATE HTTP/1.1
> Host: ec2-54-174-138-73.compute-1.amazonaws.com:9870
> User-Agent: curl/7.76.1
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 307 Temporary Redirect
< Date: Sat, 06 Nov 2021 10:59:12 GMT
< Cache-Control: no-cache
< Expires: Sat, 06 Nov 2021 10:59:12 GMT
< Date: Sat, 06 Nov 2021 10:59:12 GMT
< Pragma: no-cache
< X-Content-Type-Options: nosniff
< X-FRAME-OPTIONS: SAMEORIGIN
< X-XSS-Protection: 1; mode=block
< Location: http://ip-172-31-0-150.ec2.internal:9864/webhdfs/v1/tmp/webhdfs_test_file?op=CREATE&namenoderpcaddress=ha-nn-uri&createflag=&createparent=true&overwrite=false
< Content-Type: application/octet-stream
< Content-Length: 0
<
* Connection #0 to host ec2-54-174-138-73.compute-1.amazonaws.com left intact
* Issue another request to this URL: 'http://ip-172-31-0-150.ec2.internal:9864/webhdfs/v1/tmp/webhdfs_test_file?op=CREATE&namenoderpcaddress=ha-nn-uri&createflag=&createparent=true&overwrite=false'
*   Trying 172.31.0.150:9864...
* Connected to ip-172-31-0-150.ec2.internal (172.31.0.150) port 9864 (#1)
> PUT /webhdfs/v1/tmp/webhdfs_test_file?op=CREATE&namenoderpcaddress=ha-nn-uri&createflag=&createparent=true&overwrite=false HTTP/1.1
> Host: ip-172-31-0-150.ec2.internal:9864
> User-Agent: curl/7.76.1
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 100 Continue
* Mark bundle as not supporting multiuse
< HTTP/1.1 201 Created
< Location: hdfs://ha-nn-uri/tmp/webhdfs_test_file
< Content-Length: 0
< Access-Control-Allow-Origin: *
< Connection: close
<
* Closing connection 1

ActiveのNameNode・DataNodeにはログがあります(StandbyのDataNodeにはない)

NameNode

 grep "webhdfs_test_file" /var/log/hadoop-hdfs/*
/var/log/hadoop-hdfs/hadoop-hdfs-namenode-ip-172-31-0-7.log:2021-11-06 10:59:12,181 INFO org.apache.hadoop.hdfs.StateChange (IPC Server handler 19 on default port 8020): DIR* completeFile: /tmp/webhdfs_test_file is closed by DFSClient_NONMAPREDUCE_-1106891656_40

DataNode

 grep webhdfs_test_file /var/log/hadoop-hdfs/*
/var/log/hadoop-hdfs/hadoop-hdfs-datanode-ip-172-31-0-150.log:2021-11-06 10:59:12,181 INFO datanode.webhdfs (nioEventLoopGroup-3-3): 172.31.0.7 PUT /webhdfs/v1/tmp/webhdfs_test_file?op=CREATE&namenoderpcaddress=ha-nn-uri&createflag=&createparent=true&overwrite=false 201

ファイル作成ではStandbyにリクエストできるわけ

ファイル作成の場合、最初にリクエストを受け付けたNameNodeでは処理をせず、以下の流れで処理を行います。
この時、クライアントが最初にリクエストするNameNodeと、DataNodeが通知するNameNodeが異なっても良いため、最初にリクエストするNameNodeはActiveでなくても良いようです。

  1. (クライアント)NameNodeにリクエスト
  2. (NameNode)適当なDataNodeを選び、そのURLをリダイレクトレスポンスとして返す
  3. (クライアント)リダイレクトに従い、DataNodeにリクエスト
  4. (DataNode)ファイルの作成
  5. (DataNode)作成したファイルの情報をNameNodeに通知
  6. (NameNode)作成したファイルの情報を記録

コード

  1. NameNodeのop=CREATE受付
  2. DataNodeのop=CREATE
  3. DFSClient#createを経由して、DFSOutPutStream#newStreamForCreateでNameNodeのcreateを呼び出し
    • (なお、この呼出はWebHDFSではなくRPCです)
  4. データを書き込み
  5. closeImplcompleteFile
    経由して、NameNodeのcompleteを呼び出し

Discussion