## HDFS介绍
Hadoop分布式文件系统(HDFS)被设计成适合运行在通用硬件(commodity hardware)上的分布式文件系统。它和现有的分布式文件系统有很多共同点。但同时,它和其他的分布式文件系统的区别也是很明显的。HDFS是一个高度容错性的系统,适合部署在廉价的机器上。HDFS能提供高吞吐量的数据访问,非常适合大规模数据集上的应用。HDFS放宽了一部分POSIX约束,来实现流式读取文件系统数据的目的。HDFS在最开始是作为Apache Nutch搜索引擎项目的基础架构而开发的。HDFS是Apache Hadoop Core项目的一部分。
目前使用golang调用hdfs的方式有以下几种:
- 使用go http 调用webHDFS/httpfs接口实现。
- 使用c lib提供的API, 并用cgo进行封装,然后调用实现。
- 使用第三方golang客户端实现。([https://github.com/colinmarc/hdfs](https://github.com/colinmarc/hdfs))。
Hadoop 官方接口地址:[http://hadoop.apache.org/docs/stable/hadoop-project-dist/hadoop-hdfs/WebHDFS.html](http://hadoop.apache.org/docs/stable/hadoop-project-dist/hadoop-hdfs/WebHDFS.html)
我们这里仅介绍第一种方式,方便大家熟悉调用流程。github上的第三方client功能较全,但对golang版本有要求(1.10.3及以上),建议低版本慎用。
### webHDFS/httpfs
官网针对这块接口介绍已经足够详细了,也提供了curl命令调用实例,大家通过go http实现对用的http接口即可。
#### **Create**
在HDFS上创建一个文件,可直接put文件内容。该接口有curl命令实例:
```
curl -i -X PUT -T <LOCAL_FILE> "http://<DATANODE>:<PORT>/webhdfs/v1/<PATH>?op=CREATE..."
```
实际操作:
```shell
curl -i -L -XPUT -T /home/xxx/test.json -H "content-type:application/octet-stream" "http://10.19.241.13:14000/webhdfs/v1/mytest/test.json?op=CREATE&user.name=root"
```
下面用golang实现,以上传一个本地文件为例:
```go
package main
import (
"bytes"
"errors"
"io"
"io/ioutil"
"net/http"
"os"
"path"
"fmt"
)
/* webHDFS方式:此处仅作实例,直接填写的为datanode地址,若改为namenode地址,则需要重定向到datanode
后再调用
httpfs方式:直接填写namenode地址,无需重定向
*/
var HDFSURLPrefix = "http://10.19.241.13:14000/webhdfs/v1/mydir"
func createFromData(bucket string, fileName string, data []byte) error {
url := HDFSURLPrefix + "/" + path.Join(bucket, fileName) + "?op=create&data=true&user.name=root"
req, err := http.NewRequest("PUT", url, bytes.NewReader(data))
if err != nil {
fmt.Println(fmt.Errorf("url(%v) NewRequest: %v", url, err))
return err
}
req.Header.Set("Content-Type", "application/octet-stream")
rep, err := http.DefaultClient.Do(req)
if err != nil {
fmt.Println(fmt.Errorf("url(%v) DefaultClient.Do: %v", url, err))
return err
}
if rep.StatusCode != http.StatusCreated {
fmt.Println(fmt.Errorf("url(%v) rep not ok, req(%v)", url, rep))
return err
}
body, err := ioutil.ReadAll(rep.Body)
if err != nil {
fmt.Println(fmt.Errorf("url(%v) rep body read failed: %v", url, err))
return err
}
fmt.Printf("url(%v) get req ok, body(%v)\n", url, string(body))
return nil
}
func main() {
data, err := ioutil.ReadFile("/home/xxx/test.json")
if err != nil {
fmt.Println(fmt.Errorf("read file failed:%v", err))
return
}
err = createFromData("xxx", "test.json", data)
if err != nil {
fmt.Println(fmt.Errorf("create hdfs file failed:%v", err))
return
}
}
```
### 注意:
以上代码仅简单的实现了上传一个本地文件到HDFS的功能。针对较大文件,此代码并不实用(单次readAll不合理)。这时候可以使用Append接口对大文件进行分段上传。
另外,需要注意HDFS的namenode和datanode区别,由于hdfs一般部署在集群环境中,直接访问datanode不太现实。webHDFS调用时需要通过namenode重定向到datanode。为避免此情况,建议调整为httpfs方式,直接访问namenode地址。
参考文档:
[http://hadoop.apache.org/docs/stable/hadoop-project-dist/hadoop-hdfs/WebHDFS.html](http://hadoop.apache.org/docs/stable/hadoop-project-dist/hadoop-hdfs/WebHDFS.html)
有疑问加站长微信联系(非本文作者))