将目录而不是文件传递到hadoop流媒体?

将目录而不是文件传递到hadoop流媒体?,hadoop,hadoop-streaming,Hadoop,Hadoop Streaming,在我的工作中,我需要解析许多历史日志集。个人客户(数千)可能有数百个按日期划分的日志子目录。例如: 日志/Customer_One/2011-01-02-001 日志/Customer_One/2012-02-03-001 日志/客户号/2012-02-03-002 日志/Customer_Two/2009-03-03-001 日志/Customer_Two/2009-03-03-002 每个单独的日志集本身可能有五到六个级别,包含数千个文件 因此,我实际上希望单个映射作业能够处理遍历子目录

在我的工作中,我需要解析许多历史日志集。个人客户(数千)可能有数百个按日期划分的日志子目录。例如:

  • 日志/Customer_One/2011-01-02-001
  • 日志/Customer_One/2012-02-03-001
  • 日志/客户号/2012-02-03-002
  • 日志/Customer_Two/2009-03-03-001
  • 日志/Customer_Two/2009-03-03-002
每个单独的日志集本身可能有五到六个级别,包含数千个文件

因此,我实际上希望单个映射作业能够处理遍历子目录的操作:简单地枚举单个文件是我的分布式计算问题的一部分

不幸的是,当我尝试将一个只包含日志子目录的目录传递给Hadoop时,它会抱怨我无法将这些子目录传递给映射器。(同样,我写了一封接受子目录作为输入的信):

$hadoop jar“${hadoop_HOME}/contrib/streaming/hadoop streaming-${hadoop_VERSION}.jar”-输入file:///mnt/logs/Customer_Name/ -文件mapper.sh-映射器“mapper.sh”-文件reducer.sh-reducer“reducer.sh”-输出。

[……]

12/04/10 12:48:35错误安全性。用户组信息:PriviledEdActionException as:cloudera(身份验证:简单)原因:java.io.IOException:非文件:文件:/mnt/logs/Customer_Name/2011-05-20-003 12/04/10 12:48:35错误流。StreamJob:错误启动作业:不是文件:文件:/mnt/logs/Customer_Name/2011-05-20-003 流式处理命令失败! [cloudera@localhost~]$


有没有一种简单的方法可以说服Hadoop streaming允许我将目录分配为工作项?

我想您需要研究编写一种自定义InputFormat,您也可以传递根目录,它将为每个客户创建一个拆分,然后,每个拆分的记录读取器将执行目录漫游,并将文件内容推送到映射器中。

Hadoop支持将输入路径作为正则表达式。我没有尝试过很多复杂的正则表达式,但是简单的占位符*确实有效

因此,在您的情况下,我认为如果您将以下内容作为输入路径,它将起作用:

file:///mnt/logs/Customer_Name/*/*

最后一个星号可能不需要,因为最终目录中的所有文件都会自动添加为输入路径。

通配符/globs应该可以工作,请尝试
-inputfile:///mnt/logs/Customer_*/**/*.log
Globbing并不是答案:首先,它只能在目录树中找到给定级别的文件,而不是多个级别的文件;其次,正如我最初描述的那样,目录和子目录的数量是巨大的(事实上,远远超出了没有xargs扩展的shell的范围),而遍历该树的时间正是我想要解决的问题的一部分。(仅仅用1ms rtt执行您所说的全局绑定就需要几天的时间。)有一段时间我记得hadoop支持带有双星(**)符号的递归全局绑定,但在我的控制台中的快速测试表明,我不清楚hadoop流是否可以接受任何其他输入格式。可以吗请参阅
-inputformat
参数Yep。但如果我将其更改为不同的现有InputFormat(例如org.apache.hadoop.mapred.KeyValueTextInputFormat),它仍然会抱怨“不是文件”。我是说,您需要编写自定义输入格式,您的用例中不存在预封装的hadoop。如果你没有不同级别的目录结构和数千个嵌套的文件和目录,那么这也许你可以知道为什么会被否决?这确实是一种将目录作为输入路径传递的简单方法,只是您需要事先知道其深度。我已经成功地使用过很多次了。它不起作用。它只查找给定级别的文件。