《Hadoop MapReduce实战手册》一2.9 使用HDFS的C API(libhdfs)

简介:

本节书摘来异步社区《Hadoop MapReduce实战手册》一书中的第2章,第2.9节,作者: 【美】Srinath Perera , Thilina Gunarathne 译者: 杨卓荦 责编: 杨海玲,更多章节内容可以访问云栖社区“异步社区”公众号查看。

2.9 使用HDFS的C API(libhdfs)

Hadoop MapReduce实战手册
libhdfs是一个原生共享库,提供了一套C API,允许非Java程序与HDFS进行交互。libhdfs使用JNI通过Java与HDFS进行交互。

准备工作
目前的Hadoop发行版中包含了为32位和64位Linux操作系统预编译的libhdfs库。如果你的操作系统与预编译库不兼容,则可能需要下载Hadoop的标准发行版并从源代码编译libhdfs库。有关编译libhdfs库的信息请参见2.10节。

操作步骤
下列步骤显示了如何在HDFS环境下使用HDFS的C API执行操作。

  1. 下面的示例程序会在HDFS中创建一个新文件,向新建文件中写入一些文本信息,并从HDFS读回该文件。用HDFS集群中NameNode的相关值替换NAMENODE_HOSTNAME和端口变量。该hdfs_cpp_demo.c源文件中的源代码包位于该文件夹的HDFS_C_API目录中。
#include "hdfs.h"

int main(intargc, char **argv) {

hdfsFSfs =hdfsConnect( "NAMENODE_HOSTNAME,PORT");

if (!fs) {
     fprintf(stderr, "Cannot connect to HDFS.\n");
     exit(-1);
  }

char* fileName = "demo_c.txt";
char* message = "Welcome to HDFS C API!!!";
int size = strlen(message);

int exists = hdfsExists(fs, fileName);

if (exists > -1) {
   fprintf(stdout, "File %s exists!\n", fileName);
}else{
 // Create and open file for writing
 hdfsFileoutFile = hdfsOpenFile(fs, fileName, O_WRONLY|O_CREAT, 0, 0, 0);
if (!outFile) {
 fprintf(stderr, "Failed to open %s for writing!\n", fileName);
       exit(-2);
  }

  // write to file
hdfsWrite(fs, outFile, (void*)message, size);
  hdfsCloseFile(fs, outFile);
  }

  // Open file for reading
hdfsFileinFile = hdfsOpenFile(fs, fileName, O_RDONLY, 0, 0, 0);
  if (!inFile) {
fprintf(stderr, "Failed to open %s for reading!\n", fileName);
     exit(-2);
  }

  char* data = malloc(sizeof(char) * size);
  // Read from file.
tSizereadSize = hdfsRead(fs, inFile, (void*)data, size);
fprintf(stdout, "%s\n", data);
  free(data);

hdfsCloseFile(fs, inFile);
hdfsDisconnect(fs);
  return 0;
}
  1. 通过使用如下gcc命令编译上面的程序。当编译时,需要链接libhdfs和JVM库。因此,还必须包括Java安装路径的JNI头文件。一个示例编译命令如下所示。将ARCH和架构依赖的路径替换成当前系统的路径。
>gcchdfs_cpp_demo.c \
-I $HADOOP_HOME/src/c++/libhdfs \
-I $JAVA_HOME/include \
-I $JAVA_HOME/include/linux/ \
-L $HADOOP_HOME/c++/ARCH/lib/ \
-L $JAVA_HOME/jre/lib/ARCH/server\
-l hdfs -ljvm -o hdfs_cpp_demo
  1. 重置环境变量CLASSPATH,将其指向Hadoop的依赖环境。一种保险的方法是将$HADOOP_HOME和$HADOOP_HOME/lib中的所有jar文件全部包括在环境变量中。
export CLASSPATH=$HADOOP_HOME/hadoop-core-xx.jar:...

Ant构建脚本生成类路径

在2.8节步骤2中给出的build文件的末尾,添加下面的Anttarget。本章源码包的HDFS_C_API文件夹中提供了修改后的build.xml脚本。

<target name="print-cp">
   <property name="classpath"`
     refid="hadoop-classpath"/>`
   <echo message="classpath= ${classpath}"/>`
</target>`

用ant print-cp执行Ant构建,之后会生成一个包含$HADOOP_HOME和$HADOOP_HOME/lib中的所有jar文件名的字符串。复制这个字符串导出到CLASSPATH环境变量中。

  1. 执行程序。
>LD_LIBRARY_PATH=$HADOOP_HOME/c++/ARCH/lib:$JAVA_HOME/jre/lib/ARCH/
server./hdfs_cpp_demo

Welcome to HDFS C API!!!

工作原理
首先,我们通过hdfsConnect命令输入NameNode的主机名(或IP地址)和端口来连接到一个HDFS集群。hdfsConnectAsUser命令可以作为一个特定的用户连接到一个HDFS集群。

hdfsFSfs =hdfsConnect("NAMENODE_HOSTNAME",PORT);

使用hdfsOpenFile命令新建文件,并获得新新建文件的句柄。O_WRONLY | O_CREAT标志表示新建一个文件或重写现有文件,并用只写模式打开它。其他支持的标志还有O_RDONLY和O_APPEND。该hdfsOpenFile命令的第四、第五和第六个参数分别表示进行读/写操作的缓冲区大小、块的冗余因子和新创建文件的块大小。如果想使用这三个参数的默认值,可以将它们指定为0。

hdfsFileoutFile = hdfsOpenFile(fs, fileName,flags, 0, 0, 0);

该hdfsWrite指令将提供的数据写入到outFile句柄指定的文件中。数据大小需要以字节数为单位指定。

hdfsWrite(fs, outFile, (void*)message, size);

hdfsRead命令从inFile指定的文件中读取数据。需要提供以字节为单位的缓冲区大小作为第四个参数。hdfsRead命令返回文件读取的实际字节数,该数量可能小于缓冲区大小。如果想要确保从文件中读取一定的字节数,最好是在循环内使用hdfsRead命令,直到读完了指定的字节数为止。

char* data = malloc(sizeof(char) * size);
tSizereadSize = hdfsRead(fs, inFile, (void*)data, size);

更多参考
HDFS的C API(libhdfs)支持的文件系统操作比前面示例中用到的多。请参见$HADOOP_HOME/src/
c++/libhdfs/hdfs.h头文件获得更多有关的详细信息。

使用HDFS的配置文件配置
还可以使用HDFS的配置文件来告诉libhdfsNameNode的主机名和端口号,而不是通过hdfs-
Connect命令以参数的方式传入。

  1. 在hdfsConnect命令中,将NameNode的主机名和端口号改为"default"和0。(将主机名设置为NULL将使libhdfs使用本地文件系统)。
hdfsFSfs = hdfsConnect("default",0);
  1. 将HDFS安装的conf目录添加到CLASSPATH环境变量中。
export CLASSPATH=$HADOOP_HOME/hadoop-core-xx.jar:...:$HADOOP_HOME/conf
相关文章
|
2月前
|
分布式计算 Kubernetes Hadoop
大数据-82 Spark 集群模式启动、集群架构、集群管理器 Spark的HelloWorld + Hadoop + HDFS
大数据-82 Spark 集群模式启动、集群架构、集群管理器 Spark的HelloWorld + Hadoop + HDFS
166 6
|
2月前
|
分布式计算 资源调度 Hadoop
大数据-80 Spark 简要概述 系统架构 部署模式 与Hadoop MapReduce对比
大数据-80 Spark 简要概述 系统架构 部署模式 与Hadoop MapReduce对比
68 2
|
2月前
|
SQL 分布式计算 监控
Hadoop-20 Flume 采集数据双写至本地+HDFS中 监控目录变化 3个Agent MemoryChannel Source对比
Hadoop-20 Flume 采集数据双写至本地+HDFS中 监控目录变化 3个Agent MemoryChannel Source对比
62 3
|
2月前
|
SQL 分布式计算 Hadoop
Hadoop-14-Hive HQL学习与测试 表连接查询 HDFS数据导入导出等操作 逻辑运算 函数查询 全表查询 WHERE GROUP BY ORDER BY(一)
Hadoop-14-Hive HQL学习与测试 表连接查询 HDFS数据导入导出等操作 逻辑运算 函数查询 全表查询 WHERE GROUP BY ORDER BY(一)
47 4
|
2月前
|
存储 分布式计算 资源调度
大数据-04-Hadoop集群 集群群起 NameNode/DataNode启动 3台公网云 ResourceManager Yarn HDFS 集群启动 UI可视化查看 YarnUI(一)
大数据-04-Hadoop集群 集群群起 NameNode/DataNode启动 3台公网云 ResourceManager Yarn HDFS 集群启动 UI可视化查看 YarnUI(一)
76 5
|
2月前
|
分布式计算 资源调度 Hadoop
Hadoop-10-HDFS集群 Java实现MapReduce WordCount计算 Hadoop序列化 编写Mapper和Reducer和Driver 附带POM 详细代码 图文等内容
Hadoop-10-HDFS集群 Java实现MapReduce WordCount计算 Hadoop序列化 编写Mapper和Reducer和Driver 附带POM 详细代码 图文等内容
98 3
|
2月前
|
SQL 分布式计算 Hadoop
Hadoop-19 Flume Agent批量采集数据到HDFS集群 监听Hive的日志 操作则把记录写入到HDFS 方便后续分析
Hadoop-19 Flume Agent批量采集数据到HDFS集群 监听Hive的日志 操作则把记录写入到HDFS 方便后续分析
48 2
|
2月前
|
SQL
Hadoop-14-Hive HQL学习与测试 表连接查询 HDFS数据导入导出等操作 逻辑运算 函数查询 全表查询 WHERE GROUP BY ORDER BY(二)
Hadoop-14-Hive HQL学习与测试 表连接查询 HDFS数据导入导出等操作 逻辑运算 函数查询 全表查询 WHERE GROUP BY ORDER BY(二)
39 2
|
2月前
|
分布式计算 Hadoop 网络安全
Hadoop-08-HDFS集群 基础知识 命令行上机实操 hadoop fs 分布式文件系统 读写原理 读流程与写流程 基本语法上传下载拷贝移动文件
Hadoop-08-HDFS集群 基础知识 命令行上机实操 hadoop fs 分布式文件系统 读写原理 读流程与写流程 基本语法上传下载拷贝移动文件
38 1
|
2月前
|
分布式计算 资源调度 数据可视化
Hadoop-06-Hadoop集群 历史服务器配置 超详细 执行任务记录 JobHistoryServer MapReduce执行记录 日志聚合结果可视化查看
Hadoop-06-Hadoop集群 历史服务器配置 超详细 执行任务记录 JobHistoryServer MapReduce执行记录 日志聚合结果可视化查看
43 1