Hadoop 初学者指南(四)
十、使用 Flume 收集数据
在前两章中,我们看到了 Have 和 Sqoop 如何为 Hadoop 提供关系数据库接口,并允许它与“真实”数据库交换数据。 虽然这是一个非常常见的用例,但当然,我们可能希望将许多不同类型的数据源引入 Hadoop。
在本章中,我们将介绍:
- Hadoop 中常用处理的数据概述
- 将这些数据放入 Hadoop 的简单方法
- Apache Flume 如何让这项任务变得容易得多
- 简单到复杂的 Flume 设置的常用图案
- 无论采用何种技术都需要考虑的常见问题,如数据生命周期
关于 AWS 的说明
本章讨论的 AW 比本书中的任何其他 AW 都要少。 事实上,在这一节之后我们甚至不会提到它。 亚马逊没有类似于 Flume 的服务,所以我们也没有特定于 AWS 的产品可以探索。 另一方面,在使用 Flume 时,无论是在本地主机上还是在 EC2 虚拟实例上,它的工作方式都完全相同。 因此,本章的其余部分不假定执行这些示例的环境;它们将在每个环境上执行相同的操作。
数据数据无处不在...
在讨论 Hadoop 与其他系统的集成时,很容易将其视为一对一模式。 数据来自一个系统,在 Hadoop 中处理,然后传递到第三个系统。
事情可能在第一天就是这样,但实际情况往往是一系列相互协作的组件,数据流在它们之间来回传递。 我们如何以可维护的方式构建这个复杂的网络是本章的重点。
数据类型
为了便于讨论,我们将数据分为两大类:
- 网络流量、,其中数据由系统生成并通过网络连接发送
- 文件数据,其中数据是由系统生成的,并写入文件系统上某处的文件
除了检索数据的方式外,我们不假设这些数据类别有任何不同。
让网络流量进入 Hadoop
当我们说网络数据时,我们指的是通过 HTTP 连接从 Web 服务器检索的信息、客户端应用拉取的数据库内容或通过数据总线发送的消息。 在每种情况下,数据都由客户端应用检索,该应用要么通过网络拉取数据,要么侦听数据到达。
备注
在以下几个示例中,我们将使用curl实用程序检索或发送网络数据。 确保它已安装在您的系统上,如果没有,请安装它。
该采取行动了-将 Web 服务器数据导入 Hadoop
让我们来看看我们如何简化地将数据从 Web 服务器复制到 HDFS。
-
将 NameNode Web 界面的文本检索到本地文件:
$ curl localhost:50070 > web.txt -
Check the file size:
$ ls -ldh web.txt您将收到以下响应:
-rw-r--r-- 1 hadoop hadoop 246 Aug 19 08:53 web.txt -
将文件复制到 HDFS:
$ hadoop fs -put web.txt web.txt -
Check the file on HDFS:
$ hadoop fs -ls您将收到以下响应:
Found 1 items -rw-r--r-- 1 hadoop supergroup 246 2012-08-19 08:53 /user/hadoop/web.txt
刚刚发生了什么?
这里有应该没有什么令人惊讶的地方。 我们使用curl实用程序从托管 NameNode Web 界面的嵌入式 Web 服务器检索网页,并将其保存到本地文件。 我们检查文件大小,将其复制到 HDFS,并验证文件是否已成功传输。
这里要注意的不是一系列操作--毕竟这只是我们自第 2 章、启动并运行以来一直使用的hadoop fs命令的另一种用法--而是我们应该讨论使用的模式。
虽然我们想要的数据位于 Web 服务器中,并且可以通过 HTTP 协议进行访问,但开箱即用的 Hadoop 工具非常基于文件,并且不具备对此类远程信息源的任何内在支持。 这就是我们需要在将网络数据传输到 HDFS 之前将其复制到文件中的原因。
当然,我们可以通过第 3 章,编写 MapReduce 作业中提到的编程接口将数据直接写入 HDFS,这样做效果很好。 然而,这需要我们开始为需要从中检索数据的每个不同的网络源编写自定义客户端。
来个围棋英雄
以编程方式检索数据并将其写入 HDFS 是一项非常强大的功能,值得探索一下。 非常流行的 HTTPJava 库是Apache****HTTPClient,位于hc.apache.org/httpcompone…的HTTP Components项目中。
使用 HTTPClient 和 Java HDFS 接口像以前一样检索网页并将其写入 HDFS。
将文件导入 Hadoop
我们前面的示例展示了将基于文件的数据导入 Hadoop 的最简单方法,以及标准命令行工具或编程 API 的使用。 这里没有什么可讨论的,因为这是我们在整本书中一直在讨论的一个主题。
隐藏问题
尽管前面的方法都很好,但有几个原因说明它们可能不适合生产使用。
将网络数据保存在网络上
我们将通过网络访问的数据复制到文件,然后再将其放到 HDFS 上的模型会对性能产生影响。 由于往返到磁盘(系统中最慢的部分)会增加延迟。 对于在一次调用中检索的大量数据来说,这可能不是问题-尽管磁盘空间可能会成为一个问题-但对于高速检索的少量数据,这可能会成为一个真正的问题。
Hadoop 依赖项
对于基于文件的方法,前面提到的模型中隐含着这样一点:我们可以访问文件的点必须能够访问 Hadoop 安装,并且必须配置为知道集群的位置。 这可能会在系统中增加额外的依赖关系;这可能会迫使我们将 Hadoop 添加到真正需要对其一无所知的主机。 我们可以通过使用 SFTP 等工具将文件检索到支持 Hadoop 的计算机,并从那里复制到 HDFS 来缓解此问题。
可靠性
请注意,在前面的方法中完全缺少错误处理。 我们使用的工具没有内置的重试机制,这意味着我们需要围绕每个数据检索包装一定程度的错误检测和重试逻辑。
重新创建控制盘
最后一点可能涉及到这些特殊方法的最大问题;很容易得到十几个不同的命令行工具和脚本字符串,每个字符串都执行非常相似的任务。 随着时间的推移,重复工作和更困难的错误跟踪方面的潜在成本可能会很大。
通用框架方法
在这一点上,任何有企业计算经验的人都会认为,这听起来像是使用某种类型的公共集成框架最好解决的问题。 这是完全正确的,并且确实是诸如Enterprise Application Integration(EAI)等领域所熟知的一般产品类型。
不过,我们需要的是一个框架,它能够识别 Hadoop,并且可以轻松地与 Hadoop(以及相关项目)集成,而不需要花费大量精力编写自定义适配器。 我们可以创建我们自己的,但是让我们看一下Apache Flume,它提供了我们需要的大部分内容。
Apache Flume 简介
Flume 在Hadoop找到,是另一个与 flume.apache.org 紧密集成的 Apache 项目,我们将在本章的剩余部分对其进行探讨。
在我们解释 Flume 可以做什么之前,让我们先弄清楚它不能做什么。 Flume 被描述为用于检索和分发日志的系统,这意味着面向行的文本数据。 它不是一个通用的数据分发平台;尤其是,不要指望使用它来检索或移动二进制数据。
但是,由于在 Hadoop 中处理的绝大多数数据都符合这一描述,因此 Flume 很可能会满足您的许多数据检索需求。
备注
Flume 也不是像我们在第 5 章、高级 MapReduce 技术中使用的Avro那样的通用数据序列化框架,也不是Thrift和Protocol Buffers等类似技术。 正如我们将看到的,Flume 对数据格式进行了假设,并且没有提供序列化这些格式以外的数据的方法。
Flume 提供了从多个源检索数据、将其传递到远程位置(可能是扇出或管道模型中的多个位置),然后将其传递到各种目的地的机制。 虽然它确实有一个允许开发自定义源和目标的编程 API,但是这个基础产品对许多最常见的场景都有内置支持。 让我们把它安装好,然后看一看。
关于版本化的说明
最近,Flume 经历了一些重大变化。 原始 Flume(现已重命名为Flume OG用于原始生成)将被Flume NG(下一代)取代。 虽然总体原则和功能非常相似,但实现方式却大相径庭。
因为 Flume NG 是未来的,我们将在本书中介绍它。 不过,在一段时间内,它将缺少更成熟的 Flume OG 的几个功能,所以如果您发现 Flume NG 没有满足的特定要求,那么可能值得看看 Flume OG。
行动时间-安装和配置 Flume
让我们下载并安装 Flume。
-
从flume.apache.org/检索最新的 Flume NG 二进制文件,并将其下载并保存到本地文件系统。
-
将文件移动到所需位置并解压缩:
$ mv apache-flume-1.2.0-bin.tar.gz /opt $ tar -xzf /opt/apache-flume-1.2.0-bin.tar.gz -
创建指向安装的符号链接:
$ ln -s /opt/apache-flume-1.2.0 /opt/flume -
定义
FLUME_HOME环境变量:Export FLUME_HOME=/opt/flume -
将 Flume
bin目录添加到您的路径:Export PATH=${FLUME_HOME}/bin:${PATH} -
验证是否设置了
JAVA_HOME:Echo ${JAVA_HOME} -
验证 Hadoop 库是否位于类路径中:
$ echo ${CLASSPATH} -
创建将用作 Flume
conf目录的目录:$ mkdir /home/hadoop/flume/conf -
将所需文件复制到
conf目录:$ cp /opt/flume/conf/log4j.properties /home/hadoop/flume/conf $ cp /opt/flume/conf/flume-env.sh.sample /home/hadoop/flume/conf/flume-env.sh -
编辑
flume-env.sh并设置JAVA_HOME。
刚刚发生了什么?
Flume 安装非常简单,并且与我们之前安装的工具具有类似的先决条件。
首先,我们检索了最新版本的 Flume NG(任何 1.2.x 或更高版本都可以),并将其保存到本地文件系统。 我们将其移动到所需位置,将其解压缩,并创建了指向该位置的方便符号链接。
我们需要定义FLUME_HOME环境变量,并将安装目录中的bin目录添加到类路径中。 如前所述,这可以直接在命令行上完成,也可以在方便的脚本中完成。
Flume 要求定义JAVA_HOME,我们证实了这一点。 它还需要 Hadoop 库,所以我们检查 Hadoop 类是否在类路径中。
虽然最后几个步骤将用于生产,但并不是严格意义上的演示所必需的。 Flume 查找配置目录,其中包含定义默认日志记录属性和环境设置变量(如JAVA_HOME)的文件。 我们发现 Flume 在正确设置此目录时的性能是最可预测的,因此我们现在就这样做了,不需要在很长时间内更改它。
我们假设/home/hadoop/flume是存储 Flume 配置和其他文件的工作目录;根据您的系统的需要更改此目录。
使用 Flume 捕获网络数据
现在我们已经安装了 Flume,让我们使用它来捕获一些网络数据。
在日志文件中捕获网络流量的操作时间
在第一个实例中,让我们使用一个简单的 Flume 配置,该配置将把网络数据捕获到主 Flume 日志文件中。
-
在您的 Flume 工作目录中创建以下文件
agent1.conf:agent1.sources = netsource agent1.sinks = logsink agent1.channels = memorychannel agent1.sources.netsource.type = netcat agent1.sources.netsource.bind = localhost agent1.sources.netsource.port = 3000 agent1.sinks.logsink.type = logger agent1.channels.memorychannel.type = memory agent1.channels.memorychannel.capacity = 1000 agent1.channels.memorychannel.transactionCapacity = 100 agent1.sources.netsource.channels = memorychannel agent1.sinks.logsink.channel = memorychannel -
Start a Flume agent:
$ flume-ng agent --conf conf --conf-file 10a.conf --name agent1上述命令的输出如下图所示:
-
在另一个窗口中,打开到本地主机上端口 3000 的 telnet 连接,然后键入一些文本:
$ curl telnet://localhost:3000 Hello OK Flume! OK -
使用Ctrl+C关闭卷曲连接。
-
Look at the Flume log file:
$ tail flume.log您将收到以下响应:
2012-08-19 00:37:32,702 INFO sink.LoggerSink: Event: { headers:{} body: 68 65 6C 6C 6F Hello } 2012-08-19 00:37:32,702 INFO sink.LoggerSink: Event: { headers:{} body: 6D 65 Flume }
刚刚发生了什么?
首先,我们在 Flume 工作目录中创建了一个 Flume 配置文件。 我们稍后将更详细地讨论这一点,但现在,请考虑 Flume 通过名为source的组件接收数据,并将其写入名为Sink的目的地。
在本例中,我们创建了一个Netcat源,它在端口上监听网络连接。 您可以看到,我们将其配置为绑定到本地计算机上的端口 3000。
配置的是类型logger,毫不奇怪,它会将其输出写入日志文件。 配置文件的其余部分定义名为agent1的代理,它使用此源和接收器。
然后,我们使用flume-ng二进制文件启动 Flume 代理。 这是我们将用来启动所有 Flume 进程的工具。 请注意,我们为此命令提供了几个选项:
agent参数告诉 Flume 启动代理,该代理是数据移动中涉及的正在运行的 Flume 进程的通用名称- 如前所述,
conf目录 - 我们将要启动的进程的特定配置文件
- 配置文件中代理的名称
代理将启动,且屏幕上不会显示进一步输出。 (显然,我们将在生产环境中的后台运行该过程。)
在另一个窗口中,我们使用curl实用程序打开到本地计算机端口 3000 的 telnet 连接。 打开此类会话的传统方式当然是 telnet 程序本身,但许多 Linux 发行版默认安装了 curl;几乎没有一个使用较旧的telnet实用程序。
我们在每行键入一个单词并按Enter,然后使用Ctrl+C命令终止会话。 最后,我们查看正在写入 Flume 工作目录的flume.log文件,并看到我们键入的每个单词都有一个条目。
将操作记录到控制台的时间
查看日志文件并不总是很方便,特别是在我们已经打开代理屏幕的情况下。 让我们修改代理,使其也将事件记录到屏幕上。
-
Restart the Flume agent with an additional argument:
$ flume-ng agent --conf conf --conf-file 10a.conf --name agent1 -Dflume.root.logger=INFO,console您将收到以下响应:
Info: Sourcing environment configuration script /home/hadoop/flume/conf/flume-env.sh … org.apache.flume.node.Application --conf-file 10a.conf --name agent1 2012-08-19 00:41:45,462 (main) [INFO - org.apache.flume.lifecycle.LifecycleSupervisor.start(LifecycleSupervisor.java:67)] Starting lifec -
在另一个窗口中,通过 cURL:
$ curl telnet://localhost:3000连接到服务器
-
Type in
HelloandFlumeon separate lines, hit Ctrl + C, and then check the agent window:
刚刚发生了什么?
我们添加了这个示例,因为它在调试或创建新流时变得非常有用。
如上例所示,默认情况下,Flume 会将其日志写入文件系统上的一个文件。 更确切地说,这是在我们的conf目录中的 log4j 属性文件中指定的默认行为。 有时,我们希望获得更即时的反馈,而无需不断查看日志文件或更改属性文件。
通过在命令行上显式设置变量flume.root.logger,我们可以覆盖默认的记录器配置,并将输出直接发送到代理窗口。 记录器是标准的 log4j,因此支持DEBUG和INFO等普通日志级别。
将网络数据写入日志文件
Flume 将其接收的数据写入日志文件的默认日志接收器行为有一些限制,特别是当我们想要在其他应用中使用捕获的数据时。 通过配置不同类型的接收器,我们可以将数据写入更多可使用的数据文件。
执行操作的时间-将命令的输出捕获到平面文件
让我们用的方法来演示这一点,同时演示一种新的源。
-
在 Flume 工作目录中创建以下文件
agent2.conf:agent2.sources = execsource agent2.sinks = filesink agent2.channels = filechannel agent2.sources.execsource.type = exec agent2.sources.execsource.command = cat /home/hadoop/message agent2.sinks.filesink.type = FILE_ROLL agent2.sinks.filesink.sink.directory = /home/hadoop/flume/files agent2.sinks.filesink.sink.rollInterval = 0 agent2.channels.filechannel.type = file agent2.channels.filechannel.checkpointDir = /home/hadoop/flume/fc/checkpoint agent2.channels.filechannel.dataDirs = /home/hadoop/flume/fc/data agent2.sources.execsource.channels = filechannel agent2.sinks.filesink.channel = filechannel -
在主目录中创建一个简单的测试文件:
$ echo "Hello again Flume!" > /home/hadoop/message -
启动代理:
$ flume-ng agent --conf conf --conf-file agent2.conf --name agent2 -
In another window, check file sink output directory:
$ ls files $ cat files/*上述命令的输出如下图所示:
刚刚发生了什么?
前面的示例遵循与前面类似的模式。 我们为 Flume 代理创建了配置文件,运行了代理,然后确认它已经捕获了我们预期的数据。
这次我们使用了 EXEC 源和file_roll接收器。 顾名思义,前者在主机上执行命令并捕获其输出作为 Flume 代理的输入。 尽管在前一种情况下,该命令只执行一次,但这只是为了说明目的。 更常见的用法是使用产生持续数据流的命令。 请注意,可以将 EXEC 接收器配置为在命令终止时重新启动该命令。
代理的输出被写入配置文件中指定的文件。 默认情况下,Flume 每 30 秒轮换(滚动)一个新文件;我们禁用此功能是为了更容易跟踪单个文件中发生的事情。
我们看到该文件确实包含指定的exec命令的输出。
日志与文件
为什么 Flume 既有日志接收器又有文件接收器,这可能不是很明显。 从概念上讲,两者做的是一样的事情,那么有什么不同呢?
实际上,记录器接收器更像是一个调试工具。 它不仅记录源捕获的信息,还添加了大量附加元数据和事件。 然而,文件接收器记录的输入数据与接收到的数据完全一样,没有任何更改-尽管如果需要的话,这是可能的,正如我们稍后将看到的那样。
在大多数情况下,您会希望文件接收器捕获输入数据,但根据您的需要,日志也可能在非生产情况下有用。
执行操作的时间-在本地平面文件中捕获远程文件
让我们展示另一个将数据捕获到文件接收器的示例。 这一次,我们将使用另一个允许它从远程客户端接收数据的 Flume 功能。
-
在 Flume 工作目录中创建以下文件
agent3.conf:agent3.sources = avrosource agent3.sinks = filesink agent3.channels = jdbcchannel agent3.sources.avrosource.type = avro agent3.sources.avrosource.bind = localhost agent3.sources.avrosource.port = 4000 agent3.sources.avrosource.threads = 5 agent3.sinks.filesink.type = FILE_ROLL agent3.sinks.filesink.sink.directory = /home/hadoop/flume/files agent3.sinks.filesink.sink.rollInterval = 0 agent3.channels.jdbcchannel.type = jdbc agent3.sources.avrosource.channels = jdbcchannel agent3.sinks.filesink.channel = jdbcchannel -
将新测试文件创建为
/home/hadoop/message2:Hello from Avro! -
启动 Flume 代理:
$ flume-ng agent –conf conf –conf-file agent3.conf –name agent3 -
在另一个窗口中,使用 Flume Avro 客户端将文件发送到代理:
$ flume-ng avro-client -H localhost -p 4000 -F /home/hadoop/message -
As before, check the file in the configured output directory:
$ cat files/*上述命令的输出如以下截图所示:
刚刚发生了什么?
与前面一样,我们创建了一个新的配置文件,这一次为代理使用了 avro 源。 回想一下第 5 章,高级 MapReduce 技术,Avro 是一个数据序列化框架;也就是说,它管理数据在网络上从一个点到另一个点的打包和传输。 与 Netcat 源类似,Avro 源需要指定其网络设置的配置参数。 在本例中,它将侦听本地计算机上的端口 4000。 代理配置为像以前一样使用文件接收器,我们照常启动它。
Flume 既有 Avro 源,也有独立的 Avro 客户端。 后者可用于读取文件并将其发送到网络上任何位置的 Avro 源。 在我们的示例中,我们只使用本地机器,但请注意,avro 客户端需要它应该将文件发送到的 avro 源的显式主机名和端口。 因此,这不是一个限制;Avro 客户端可以将文件发送到网络上任何位置的监听 Flume Avro 源。
Avro 客户端读取文件,将其发送到代理,并将其写入文件接收器。 我们通过确认文件内容是否如预期的那样位于文件接收器位置来检查此行为。
源、汇和通道
我们在前面的示例中有意使用了各种源、汇和通道,只是为了说明如何混合和匹配它们。 然而,我们还没有对它们进行过详细的探索,特别是渠道。 现在让我们更深入地挖掘一下。
来源
我们查看了三个来源:Netcat、exec 和 Avro。 Flume NG 还支持序列生成器源(主要用于测试)以及读取syslogd数据的源的 TCP 和 UDP 变体。 每个源都配置在一个代理中,在接收到足够的数据以生成 Flume 事件后,它会将这个新创建的事件发送到源所连接的通道。 尽管源可能具有与其如何读取数据、转换事件和处理故障情况相关的逻辑,但源不知道如何存储事件。 源负责将事件传递到配置的通道,而事件处理的所有其他方面对源是不可见的。
Flume
除了我们之前使用的记录器和文件滚动槽,Flume 还支持 HDFS、HBase(两种类型)、Avro(用于代理链接)、NULL(用于测试)和 IRC(用于 Internet 中继聊天服务)的接收器。 接收器在概念上类似于源,但情况相反。
接收器等待从配置的通道接收事件,它对其内部工作原理一无所知。 接收时,接收器将事件的输出处理到其特定目标,管理有关超时、重试和轮换的所有问题。
通道
那么连接信源和信宿的神秘通道是什么呢? 正如前面的名称和配置条目所暗示的那样,它们是管理事件交付的通信和保留机制。
当我们定义一个源和一个接收器时,它们读取和写入数据的方式可能会有很大的不同。 例如,EXEC 源接收数据的速度可能比文件卷接收器写入数据的速度快得多,或者源可能有需要暂停写入的时间(例如,当滚动到新文件或处理系统 I/O 拥塞时)。 因此,通道需要在源和宿之间缓冲数据,以允许数据尽可能高效地流经代理。 这就是为什么我们的配置文件的通道配置部分包含容量等元素的原因。
存储器通道最容易理解,因为事件被从源存储器读取到存储器中,并在接收器能够接收它们时传递到接收器。 但是,如果代理进程在进程中途死亡(无论是由于软件还是硬件故障),则内存通道中当前的所有事件都将永远丢失。
我们还使用的文件和JDBC通道提供事件的持久存储,以防止此类丢失。 从源读取事件后,文件通道将内容写入文件系统上的文件,该文件仅在成功传递到接收器后才会删除。 类似地,JDBC 通道使用嵌入式 Derby 数据库以可恢复的方式存储事件。
这是经典的性能与可靠性之间的权衡。 内存通道速度最快,但有数据丢失的风险。 文件和 JDBC 通道通常要慢得多,但可以有效地向接收器提供有保证的传输。 您选择哪个频道取决于应用的性质和每个事件的值。
备注
不要过于担心这种取舍;在现实世界中,答案通常是显而易见的。 此外,一定要仔细检查使用的信源和信宿的可靠性。 如果这些都是不可靠的,您无论如何都会丢弃事件,那么您会从持久通道中获益很多吗?
或者自己滚
不要觉得被现有的源、汇和渠道集合所限制。 Flume 提供了一个接口来定义您自己的实现。 此外,Flume OG 中存在的一些组件尚未整合到 Flume NG 中,但可能会在未来出现。
了解 Flume 配置文件
现在我们已经讨论了个源、接收器和通道,让我们更详细地看看前面的一个配置文件:
agent1.sources = netsource
agent1.sinks = logsink
agent1.channels = memorychannel
这些第一行命名代理,并定义与其关联的源、汇和通道。 每行可以有多个值;这些值以空格分隔:
agent1.sources.netsource.type = netcat
agent1.sources.netsource.bind = localhost
agent1.sources.netsource.port = 3000
这些行指定源的配置。 由于我们使用的是 Netcat 源,因此配置值指定它应该如何绑定到网络。 每种类型的源都有自己的配置变量。
agent1.sinks.logsink.type = logger
这指定要使用的接收器是通过命令行或 log4j 属性文件进一步配置的记录器接收器。
agent1.channels.memorychannel.type = memory
agent1.channels.memorychannel.capacity = 1000
agent1.channels.memorychannel.transactionCapacity = 100
These lines specify the channel to be used and then add the type specific configuration values. In this case we are using the memory channel and we specify its capacity but – since it is non-persistent – no external storage mechanism.
agent1.sources.netsource.channels = memorychannel
agent1.sinks.logsink.channel = memorychannel
最后的行配置用于信源和信宿的通道。 虽然我们对不同的代理使用了不同的配置文件,但我们可以将所有元素放在单个配置文件中,因为各个代理名称提供了必要的分隔。 然而,这可能会产生一个非常冗长的文件,当您刚刚学习 Flume 时,它可能会有点吓人。 我们也可以在给定的代理中有多个流,例如,我们可以将前面的两个示例组合到单个配置文件和代理中。
来个围棋英雄
就这么做吧! 在包含以下内容的单个复合代理中创建一个配置文件,该文件指定前面示例中前面的agent1和agent2的功能:
- Netcat 源及其关联的记录器接收器
- EXEC 源及其关联的文件接收器
- 两个内存通道,分别用于前面提到的源/宿对
为了让您开始,下面是组件定义的外观:
agentx.sources = netsource execsource
agentx.sinks = logsink filesink
agentx.channels = memorychannel1 memorychannel2
这一切都是关于事件的
在我们尝试另一个例子之前,让我们再讨论一个定义。 究竟什么是事件?
请记住,Flume 是明确基于日志文件的,因此在大多数情况下,一个事件等同于一行文本,后跟一个换行符。 这就是我们在使用过的源和汇上看到的行为。
然而,情况并不总是如此,例如,UDP syslogd 源将接收到的每个数据包视为通过系统传递的单个事件。 然而,在使用这些接收器和源时,这些事件定义是不可更改的,例如,在读取文件时,我们别无选择,只能使用基于行的事件。
将网络流量写入 HDFS 的操作时间
在一本关于 Hadoop 的书中关于 Flume 的讨论到目前为止还没有实际使用过 Hadoop。 让我们通过 Flume 将数据写入 HDFS 来解决这个问题。
-
在 Flume 工作目录中创建以下文件
agent4.conf:agent4.sources = netsource agent4.sinks = hdfssink agent4.channels = memorychannel agent4.sources.netsource.type = netcat agent4.sources.netsource.bind = localhost agent4.sources.netsource.port = 3000 agent4.sinks.hdfssink.type = hdfs agent4.sinks.hdfssink.hdfs.path = /flume agent4.sinks.hdfssink.hdfs.filePrefix = log agent4.sinks.hdfssink.hdfs.rollInterval = 0 agent4.sinks.hdfssink.hdfs.rollCount = 3 agent4.sinks.hdfssink.hdfs.fileType = DataStream agent4.channels.memorychannel.type = memory agent4.channels.memorychannel.capacity = 1000 agent4.channels.memorychannel.transactionCapacity = 100 agent4.sources.netsource.channels = memorychannel agent4.sinks.hdfssink.channel = memorychannel -
启动代理:
$ flume-ng agent –conf conf –conf-file agent4.conf –name agent4 -
在另一个窗口中,打开 telnet 连接并向 Flume 发送七个事件:
$ curl telnet://localhost:3000 -
Check the contents of the directory specified in the Flume configuration file and then examine the file contents:
$ hadoop fs -ls /flume $ hadoop fs –cat "/flume/*"前面命令的输出可以在下面的屏幕截图中显示:
刚刚发生了什么?
这一次,我们将 Netcat 源与 HDFS 接收器配对。 从配置文件中可以看出,我们需要指定文件的位置、任何文件前缀以及从一个文件滚动到另一个文件的策略等方面。 在本例中,我们在/flume目录中指定了文件,每个文件都以log-开头,并且每个文件中最多有三个条目(显然,这样的低值仅用于测试)。
启动代理后,我们再次使用 cURL 向 Flume 发送 7 个单字事件。 然后,我们使用 Hadoop 命令行实用程序查看目录内容,并验证我们的输入数据是否正在写入 HDFS。
请注意,第三个 HDFS 文件的扩展名为.tmp。 请记住,我们为每个文件指定了三个条目,但只输入了七个值。 因此,我们填满了两个文件,开始了另一个文件。 Flume 为当前正在写入的文件赋予了.tmp扩展名,这使得在指定要通过 MapReduce 作业处理哪些文件时,很容易区分已完成的文件和正在进行的文件。
动作添加时间戳时间
我们在前面提到过,有一些机制可以让文件数据以稍微复杂的方式写入。 让我们做一些非常常见的事情,并使用动态创建的时间戳将我们的数据写入到一个目录中。
-
将以下配置文件创建为
agent5.conf:agent5.sources = netsource agent5.sinks = hdfssink agent5.channels = memorychannel agent5.sources.netsource.type = netcat agent5.sources.netsource.bind = localhost agent5.sources.netsource.port = 3000 agent5.sources.netsource.interceptors = ts agent5.sources.netsource.interceptors.ts.type = org.apache.flume.interceptor.TimestampInterceptor$Builder agent5.sinks.hdfssink.type = hdfs agent5.sinks.hdfssink.hdfs.path = /flume-%Y-%m-%d agent5.sinks.hdfssink.hdfs.filePrefix = log- agent5.sinks.hdfssink.hdfs.rollInterval = 0 agent5.sinks.hdfssink.hdfs.rollCount = 3 agent5.sinks.hdfssink.hdfs.fileType = DataStream agent5.channels.memorychannel.type = memory agent5.channels.memorychannel.capacity = 1000 agent5.channels.memorychannel.transactionCapacity = 100 agent5.sources.netsource.channels = memorychannel agent5.sinks.hdfssink.channel = memorychannel -
启动代理:
$ flume-ng agent –conf conf –conf-file agent5.conf –name agent5 -
在另一个窗口中,打开 telnet 会话并向 Flume 发送七个事件:
$ curl telnet://localhost:3000 -
Check the directory name on HDFS and the files within it:
$ hadoop fs -ls /上述代码的输出可以在下面的屏幕截图中显示:
刚刚发生了什么?
我们对前面的配置文件进行了一些更改。 我们向 Netcat 源代码添加了interceptor规范,并将其实现类指定为TimestampInterceptor。
Flume 拦截器是可以在事件从源传递到通道之前操作和修改事件的插件。 大多数拦截器要么向事件添加元数据(如本例所示),要么根据特定条件删除事件。 除了几个内置的拦截器之外,自然还有一种用于用户定义的拦截器的机制。
我们在这里使用了时间戳拦截器,它将读取事件时的 Unix 时间戳添加到事件元数据中。 这允许我们扩展要将事件写入其中的 HDFS 路径的定义。
虽然以前我们只是将所有事件写入/flume目录,但现在我们将路径指定为/flume-%Y-%m-%d。 在运行代理并将一些数据发送到 Flume 之后,我们查看了 HDFS,发现这些变量已经展开,为目录提供了年/月/日后缀。
HDFS 接收器支持许多其他变量,如源的主机名和允许精确分区到秒级别的附加时间变量。
这里的实用程序很简单;这种简单的机制可以提供自动分区,使数据管理变得更容易,但也为 MapReduce 作业提供了更简单的数据接口,而不是将所有事件写入一个随时间而变得庞大的单个目录中。 例如,如果您的大多数 MapReduce 作业都处理每小时一次的数据,那么让 Flume 将传入事件划分到每小时一次的目录中将使您的工作变得容易得多。
准确地说,通过 Flume 的事件添加了完整的 Unix 时间戳,即精确到最接近的秒。 在我们的示例中,我们在目录规范中仅使用与日期相关的变量,如果需要每小时或更细粒度的目录分区,则将使用与时间相关的变量。
备注
这里假设处理点的时间戳足以满足您的需要。 如果正在对文件进行批处理,然后将其送入 Flume,则文件内容的时间戳可能来自前一小时的时间戳,而不是它们被处理时的时间戳。 在这种情况下,您可以编写一个自定义拦截器来根据文件内容设置时间戳头。
到 Sqoop 或到 Flume...
一个明显的问题是,如果我们想要将关系数据库中的数据导出到 HDFS 上,那么 Sqoop 或 Flume 哪一个最合适。 我们已经看到了 Sqoop 如何执行这样的导出,我们可以使用 Flume 执行类似的操作,可以使用自定义源,甚至只需将对mysql命令的调用包装在 EXEC 源中即可。
一个很好的经验法则是查看数据类型,并询问它是日志数据还是其他更复杂的数据。
Flume 在很大程度上是为了处理日志数据而创建的,它在这方面非常出色。 但在大多数情况下,Flume 网络负责将事件从源传送到汇点,而不会对日志数据本身进行任何真正的转换。 如果您在多个关系数据库中有日志数据,那么 Flume 可能是一个很好的选择,尽管我会质疑使用数据库存储日志记录的长期可伸缩性。
非日志数据可能需要只有 Sqoop 才能执行的数据操作。 我们在上一章中使用 Sqoop 执行的许多转换,比如指定要检索的列的子集,实际上使用 Flume 是不可能的。 如果您正在处理需要单独字段处理的结构化数据,那么 Flume 本身也很可能不是理想的工具。 如果您想要直接集成 Hive,那么 Sqoop 是您唯一的选择。
当然,请记住,这些工具还可以在更复杂的工作流程中协同工作。 事件可以通过 Flume 收集到 HDFS 上,通过 MapReduce 进行处理,然后通过 Sqoop 导出到关系数据库中。
行动时间-多级 Flume 网络
让我们把前面提到的几个部分放在一起,看看一个 Flume 代理如何使用另一个代理作为它的接收器。
-
将以下文件创建为
agent6.conf:agent6.sources = avrosource agent6.sinks = avrosink agent6.channels = memorychannel agent6.sources.avrosource.type = avro agent6.sources.avrosource.bind = localhost agent6.sources.avrosource.port = 2000 agent6.sources.avrosource.threads = 5 agent6.sinks.avrosink.type = avro agent6.sinks.avrosink.hostname = localhost agent6.sinks.avrosink.port = 4000 agent6.channels.memorychannel.type = memory agent6.channels.memorychannel.capacity = 1000 agent6.channels.memorychannel.transactionCapacity = 100 agent6.sources.avrosource.channels = memorychannel agent6.sinks.avrosink.channel = memorychannel -
启动按照前面创建的
agent3.conf文件配置的代理,即使用 avro 源和文件接收器:$ flume-ng client –conf conf –conf-file agent3.conf agent3 -
在第二个窗口中,启动另一个代理;该代理配置有前面的文件:
$ flume-ng client –conf conf –conf-file agent6.conf agent6 -
在第三个窗口中,使用 Avro 客户端将文件发送到每个 Flume 代理:
$ flume-ng avro-client –H localhost –p 4000 –F /home/hadoop/message $ flume-ng avro-client -H localhost -p 2000 -F /home/hadoop/message2 -
Check the output directory for files and examine the file present:
刚刚发生了什么?
首先,我们定义了一个具有 Avro 信源和 Avro 信宿的新代理。 我们以前没有使用过这个接收器;这个接收器不是将事件写入本地位置或 HDFS,而是使用 avro 将事件发送到远程源。
我们先启动这个新代理的一个实例,然后再启动前面使用的agent3的一个实例。 回想一下,该代理有一个 avro 源和一个文件滚动接收器。 我们将第一个代理中的 Avro 接收器配置为指向第二个代理中的 Avro 接收器的主机和端口,并通过这样做来构建数据路由链。
在两个代理都运行的情况下,我们然后使用 avro 客户端向每个代理发送一个文件,并确认它们都出现在配置为agent3接收器目标的文件位置。
这不仅仅是技术能力本身。 此功能是允许 Flume 构建任意复杂的分布式事件收集网络的构建块。 不是每个代理的一个副本,而是每种类型的多个代理将事件馈送到链中的下一个链接,该链接充当事件聚合点。
对多个接收器进行动作写入的时间
我们需要最后一项功能来构建这样的网络,即可以写入多个接收器的代理。 让我们创建一个。
-
将以下配置文件创建为
agent7.conf:agent7.sources = netsource agent7.sinks = hdfssink filesink agent7.channels = memorychannel1 memorychannel2 agent7.sources.netsource.type = netcat agent7.sources.netsource.bind = localhost agent7.sources.netsource.port = 3000 agent7.sources.netsource.interceptors = ts agent7.sources.netsource.interceptors.ts.type = org.apache.flume.interceptor.TimestampInterceptor$Builder agent7.sinks.hdfssink.type = hdfs agent7.sinks.hdfssink.hdfs.path = /flume-%Y-%m-%d agent7.sinks.hdfssink.hdfs.filePrefix = log agent7.sinks.hdfssink.hdfs.rollInterval = 0 agent7.sinks.hdfssink.hdfs.rollCount = 3 agent7.sinks.hdfssink.hdfs.fileType = DataStream agent7.sinks.filesink.type = FILE_ROLL agent7.sinks.filesink.sink.directory = /home/hadoop/flume/files agent7.sinks.filesink.sink.rollInterval = 0 agent7.channels.memorychannel1.type = memory agent7.channels.memorychannel1.capacity = 1000 agent7.channels.memorychannel1.transactionCapacity = 100 agent7.channels.memorychannel2.type = memory agent7.channels.memorychannel2.capacity = 1000 agent7.channels.memorychannel2.transactionCapacity = 100 agent7.sources.netsource.channels = memorychannel1 memorychannel2 agent7.sinks.hdfssink.channel = memorychannel1 agent7.sinks.filesink.channel = memorychannel2 agent7.sources.netsource.selector.type = replicating -
启动代理:
$ flume-ng agent –conf conf –conf-file agent7.conf –name agent7 -
Open a telnet session and send an event to Flume:
$ curl telnet://localhost:3000您将收到以下响应:
Replicating! Check the contents of the HDFS and file sinks: $ cat files/* $ hdfs fs –cat "/flume-*/*"上述命令的输出如下图所示:
刚刚发生了什么?
我们创建了一个配置文件,其中包含单个 Netcat 源文件以及该文件和 HDFS 接收器。 我们配置了单独的内存通道,将源连接到两个接收器。
然后,我们将源选择器类型设置为replicating,这意味着事件将被发送到所有已配置的通道。
在正常启动代理并将事件发送到源之后,我们确认该事件确实写入了文件系统和 HDFS 接收器。
选择器复制和多路复用
源选择器有两种模式,复制(如我们在这里看到的)和多路复用。 多路复用源选择器将根据指定报头字段的值使用逻辑来确定事件应该发送到哪个通道。
处理接收器故障
由于接收器是个输出目的地,因此预计接收器可能会随着时间的推移出现故障或变得无响应。 与任何输入/输出设备一样,接收器可能已饱和、空间不足或脱机。
正如 Flume 将选择器与源关联以允许我们刚才看到的复制和多路复用行为一样,它还支持接收器处理器的概念。
定义了两个信宿处理器,即故障转移信宿处理器和负载平衡信宿处理器。
接收器处理器将接收器视为在一个组内,并根据它们的类型,在事件到达时做出不同的反应。 负载平衡接收器处理器使用循环或随机算法向接收器发送事件,每次发送一个事件,以选择下一步使用哪个接收器。 如果接收器出现故障,则会在另一个接收器上重试该事件,但出现故障的接收器仍保留在池中。
相反,故障转移接收器将接收器视为优先级列表,并且仅在其上面的接收器失败时才尝试较低优先级的接收器。 出现故障的接收器将从列表中删除,并且仅在随着后续故障而增加的冷静期后才会重试。
有一个围棋英雄-处理 Flume 故障
设置具有三个已配置 HDFS 接收器的 Flume 配置,每个接收器都写入 HDFS 上的不同位置。 使用负载平衡器接收器处理器确认事件已写入每个接收器,然后使用故障转移接收器处理器显示优先顺序。
您是否可以强制代理选择优先级最高的处理器以外的处理器?
接下来,世界
我们现在已经介绍了 Flume 的大部分关键功能。 正如前面提到的,Flume 是一个框架,应该仔细考虑这一点;Flume 的部署模型比我们看到的任何其他产品都灵活得多。
它通过相对较小的一组功能实现其灵活性;通过通道将源连接到汇点,以及允许多代理或多通道配置的多种变体。 这看起来可能不是很多,但请考虑一下,可以组合这些构造块来创建如下系统,其中多个 Web 服务器场将其日志馈送到中央 Hadoop 群集:
- 每个场中的每个节点都运行一个代理,依次拉取每个本地日志文件。
- 这些日志文件被发送到一个高度可用的聚合点,每个场中的一个聚合点还执行一些处理并向事件添加附加元数据,将事件分类为三种类型的记录。
- 然后,这些一级聚合器将事件发送到访问 Hadoop 集群的一系列代理之一。 聚合器提供多个接入点,事件类型 1 和 2 被发送到第一个接入点,事件类型 3 被发送到第二个接入点。
- 在最终聚合器中,它们将事件类型 1 和 2 写入 HDFS 上的不同位置,类型 2 也写入本地文件系统。 事件类型 3 直接写入 HBase。
如此简单的原语可以组合起来构建这样复杂的系统,这真是令人惊讶!
有一个围棋英雄-下一个,世界
作为一种思维实验,尝试完成前面的场景,并确定在流程中的每个步骤都需要什么样的 Flume 设置。
更大的图景
重要的是要认识到,从一个点到另一个点“简单地”获取数据很少是您考虑数据的范围。 最近,像数据生命周期管理这样的术语被广泛使用是有原因的。 让我们简要地看一下一些需要考虑的事情,最好是在数据泛滥整个系统之前。
数据生命周期
就数据生命周期而言,要问的主要问题是,您从数据存储中获得的价值将在多长时间内大于存储成本。 永久保存数据似乎很有吸引力,但随着时间的推移,保存越来越多数据的成本将会增加。 这些成本不仅仅是财务上的;许多系统的性能随着数据量的增加而下降。
这个问题不是--或者至少不应该是--由技术因素决定的。 相反,你需要企业的价值和成本成为驱动因素。 有时数据很快就变得一文不值,有时由于竞争或法律原因,企业无法将其删除。 确定位置并采取相应的行动。
当然,请记住,在保留或删除数据之间不是一个二元决策;您还可以跨存储层迁移数据,这些存储层的成本和性能会随着时间的推移而降低。
暂存数据
在这个过程的另一边,通常值得考虑如何将数据提供给处理平台(如 MapReduce)。 对于多个数据源,您通常最不希望的就是将所有数据都放在一个巨大的卷上。
正如我们在前面看到的,Flume 能够参数化它在 HDFS 上写入的位置,这是一个很好的工具来帮助解决这个问题。 但是,通常将此初始下载点视为在处理之前写入数据的临时中转区是很有用的。 在处理之后,可以将其移动到长期目录结构中。
排程
在流程中的许多点上,我们已经讨论过,有一种隐含的需求,即需要外部任务来做一些事情。 如前所述,我们希望 MapReduce 在 Flume 将文件写入 HDFS 后对其进行处理,但是该任务是如何调度的呢? 或者,我们如何管理源主机上的后处理、旧数据的存档或删除,甚至是日志文件的删除?
其中一些任务(例如后者)可能由 Linux 上的logrotate等现有系统管理,但其他任务可能需要构建。 像cron这样显而易见的工具可能已经足够好了,但是随着系统复杂性的增加,您可能需要研究更复杂的调度系统。 在下一章中,我们将简要介绍这样一个与 Hadoop 紧密集成的系统。
摘要
本章讨论了如何跨网络检索数据并使其可在 Hadoop 中处理的问题。 正如我们所看到的,这实际上是一个更普遍的挑战,尽管我们可能会使用特定于 Hadoop 的工具,如 Flume,但这些原则并不是唯一的。 特别是,我们概述了我们可能想要写入 Hadoop 的数据类型,通常将其归类为网络数据或文件数据。 我们探索了使用现有命令行工具进行此类检索的一些方法。 虽然功能强大,但这些方法缺乏复杂性,不适合扩展到更复杂的场景中。
我们将 Flume 视为定义和管理数据(特别是来自日志文件)路由和交付的灵活框架,并了解了 Flume 体系结构,该体系结构可以看到数据到达源,通过通道进行处理,然后写入接收器。
然后,我们探索了 Flume 的许多功能,例如如何使用不同类型的源、汇和通道。 我们了解了如何将简单的构建块组合成非常复杂的系统,最后介绍了一些关于数据管理的更一般的想法。
这就是本书的主要内容。 在下一章中,我们将勾勒出一些可能令人感兴趣的其他项目,并重点介绍一些让社区参与和获得支持的方法。
十一、下一步要去哪里
正如书名所示,本书旨在让 Hadoop 初学者深入了解该技术及其应用。 正如我们在多个场合看到的那样,Hadoop 生态系统有比核心产品本身更多的东西。 在本章中,我们将快速重点介绍一些可能感兴趣的领域。
在本章中,我们将讨论:
- 我们在这本书中所涵盖的内容
- 我们在这本书中没有涵盖的内容
- 即将到来的 Hadoop 变化
- 可供选择的 Hadoop 发行版
- 其他重要的 Apache 项目
- 可选编程抽象
- 信息和帮助的来源
我们在这本书中做了什么,没有做什么
由于我们的重点是初学者,本书的目的是为您提供核心 Hadoop 概念和工具的坚实基础。 此外,我们还提供了一些其他工具的经验,帮助您将技术集成到您的基础设施中。
虽然 Hadoop 一开始只是一个核心产品,但公平地说,围绕 Hadoop 的生态系统在最近几年呈爆炸式增长。 该技术还有其他发行版本,其中一些提供了商业自定义扩展。 有太多的相关项目和工具构建在 Hadoop 之上,并为现有想法提供特定的功能或替代方法。 现在是参与 Hadoop 的一个非常令人兴奋的时刻;让我们快速了解一下外面的情况。
备注
当然,请注意,任何关于生态系统的概述都会受到作者兴趣和偏好的影响,而且在写出来的那一刻就已经过时了。 换句话说,任何时候都不要认为这就是所有可用的东西;把它看作是对胃口的刺激。
即将推出的 Hadoop 更改
在讨论其他 Hadoop 发行版之前,让我们先看一下 Hadoop 本身在不久的将来的一些变化。 我们已经讨论了 Hadoop2.0 中的 HDFS 更改,特别是新的 BackupNameNode 和 CheckpointNameNode 服务支持的 NameNode 的高可用性。 这对 Hadoop 来说是一项重要的功能,因为它将使 HDFS 更加健壮,极大地增强其企业凭证并简化群集操作。 NameNode HA 的影响很难被夸大;几乎可以肯定的是,它将成为几年后没有人能够记住我们如何生活的功能之一。
MapReduce 在这一切进行时并没有停滞不前,事实上,正在引入的变化可能不会产生太大的立竿见影的影响,但实际上要根本得多。
这些更改最初是在名称MapReduce 2.0或MRV2下开发的。 然而,现在使用的名称是Yar(Yet Another Resource Neighter),这个名称更准确,因为更改更多的是关于 Hadoop 平台,而不是 MapReduce 本身。 YAIN 的目标是在 Hadoop 上构建一个框架,允许将集群资源分配给给定的应用,并且 MapReduce 只是这些应用中的一个。
如果您现在考虑 JobTracker,它负责两个完全不同的任务:管理给定 MapReduce 作业的进度(但也识别在任何时间点哪些集群资源可用)和将资源分配给作业的各个阶段。 YAY 将这些划分为不同的角色;全局ResourceManager使用每台主机上的 NodeManagers 来管理集群的资源;以及不同的ApplicationManager(第一个示例是 MapReduce),它与 ResourceManager 通信以获取其作业所需的资源。
Year 中的 MapReduce 接口将保持不变,因此从客户端的角度来看,所有现有代码仍将在新平台上运行。 但随着新的 ApplicationManager 的开发,我们将开始看到 Hadoop 更多地被用作支持多种类型处理模型的通用任务处理平台。 移植到 Yarn 的其他模型的早期示例是基于流的处理和在科学计算中广泛使用的消息传递接口(MPI)的端口。
备选分配
回到第 2 章,启动并运行,我们转到 Hadoop 主页,从那里我们下载了安装包。 虽然看起来可能很奇怪,但这远不是获得 Hadoop 的唯一途径。 更奇怪的是,大多数生产部署都不使用 Apache Hadoop 发行版。
为什么选择替代分发?
Hadoop 是开放的源代码软件。 只要遵守管理 Hadoop 的 Apache 软件许可证,任何人都可以制作自己的软件版本。 创建替代发行版的主要原因有两个。
捆绑
一些提供商寻求构建一个预先捆绑的发行版,其中不仅包含 Hadoop,还包含其他项目,如 Have、HBase、Pig 等等。 尽管大多数项目的安装很少会有困难--除了 HBase,从历史上看,手工设置都比较困难--但可能会出现一些微妙的版本不兼容问题,直到某个特定的生产工作负载达到系统时才会出现。 捆绑发布可以提供一组预先集成的兼容版本,这些版本可以协同工作。
捆绑的发行版不仅可以在 tarball 文件中提供发行版,还可以在通过 RPM、YUM 或 APT 等包管理器轻松安装的包中提供发行版。
免费和商业扩展
作为一个拥有相对自由的发行许可的开源项目,创建者还可以自由地使用专有扩展来增强 Hadoop,这些扩展可以是免费的开源产品,也可以是商业产品。
这可能是一个有争议的问题,因为一些开源倡导者不喜欢任何成功的开源项目的商业化;对他们来说,商业实体似乎是在免费享用开源社区的成果,而不必为自己构建它。 其他人认为这是灵活的 Apache 许可的一个健康方面;基础产品永远是免费的,个人和公司可以选择是否使用商业扩展。 我们不会以任何一种方式做出判断,但请注意,这几乎是你肯定会遇到的争议。
考虑到存在其他发行版本的原因,让我们来看几个流行的例子。
适用于 Hadoop 的 Cloudera 发行版
使用最广泛的 Hadoop 发行版是 Hadoop 的Cloudera 发行版,称为CDH。 回想一下,Cloudera 是第一个创建 Sqoop 并将其贡献给开源社区的公司,现在 Doug Cutting 也在这里工作。
Cloudera 发行版可在Hadoop上获得,其中包含大量 www.cloudera.com/hadoop 产品,从 Hadoop 本身、Hive、Pig 和 HBase 到 SQOOP 和 Flume 等工具,再到 Mahout 和 Whir 等其他鲜为人知的产品。 我们稍后将讨论其中的一些内容。
CDH 有多种包格式可供选择,并以随时可用的方式部署软件。 例如,对于 NameNode、TaskTracker 等组件,基本 Hadoop 产品被分成不同的包,并且每个包都集成了标准的 Linux 服务基础设施。
CDH 是第一个广泛可用的替代发行版,其广泛的可用软件、经过验证的质量水平和免费成本使其成为非常受欢迎的选择。
除了培训、支持和咨询服务外,Cloudera 还提供额外的纯商业产品,如 Hadoop 管理工具。 详情请浏览公司网页。
Hortonworks 数据平台
2011 年,负责 Hadoop 如此多开发的雅虎部门被剥离出来,成立了一家名为Hortonworks的新公司。 他们还制作了自己的预集成 Hadoop 发行版,称为 TheHortonworks data Platfo****RM(HDP),可在hortonworks.com/products/ho…获得。
HDP 在概念上类似于 CDH,但这两种产品在侧重点上有所不同。 Hortonworks 强调 HDP 是完全开源的,包括管理工具。 他们还通过支持 Talend Open Studio 等工具将 HDP 定位为关键的集成平台。 Hortonworks 不提供商业软件;相反,它的商业模式侧重于为该平台提供专业服务和支持。
Cloudera 和 Hortonworks 都是风投支持的公司,拥有重要的工程专业知识;这两家公司都雇佣了 Hadoop 最多产的贡献者。 但是,底层技术是相同的 Apache 项目;不同之处在于它们的打包方式、使用的版本以及这些公司提供的附加增值产品。
MAPR
MapR Technologies提供了不同的类型的分发,尽管公司和分发通常简称为MapR。 在Hadoop提供,该发行版基于 www.mapr.com,但添加了许多更改和增强。
MapR 的一个主要关注点是性能和可用性,例如,它是第一个为 Hadoop NameNode 和 JobTracker 提供高可用性解决方案的发行版,您会记得(参见第 7 章,保持事物运行)是核心 Hadoop 的一个重大弱点。 它还提供与 NFS 文件系统的本机集成,这使得处理现有数据变得容易得多;MapR 用完全兼容 POSIX 的文件系统取代了 HDFS,该文件系统可以轻松地远程挂载。
MapR 提供了其发行版的社区版和企业版;并不是所有的扩展都在免费产品中提供。 除了培训和咨询外,该公司还提供支持服务,作为企业产品订阅的一部分。
IBM InfoSphere Big Insight
我们将在这里提到的最后一个发行版来自 IBM。 IBM InfoSphere Big Insights发行版可以在Hadoop BigInsight上获得,并且(与 www-01.ibm.com/software/da… Hadoop 核心的商业改进和扩展。
Big Insights 有两个版本,免费的 IBM InfoSphere Big Insights 基本版和商业的 IBM InfoSphere Big Insights 企业版。 大洞察力,大名鼎鼎! 基本版是一组增强的 Apache Hadoop 产品,添加了一些免费的管理和部署工具以及与其他 IBM 产品的集成。
EnterpriseEdition 实际上与 Basic Edition 有很大的不同;它更像是 Hadoop 之上的一层,实际上可以与 CDH 或 HDP 等其他发行版一起使用。 企业版提供了一系列数据可视化、业务分析和处理工具。 它还与其他 IBM 产品(如 InfoSphere Streams、DB2 和 GPFS)深度集成。
选择分配
可以看到,可用的发行版(我们没有涵盖所有发行版)的范围从方便的完全开源产品的打包和集成到它们上面的整个定制的集成和分析层。 不存在总体最佳分配;请仔细考虑您的需求并考虑替代方案。 由于所有以前的发行版都提供至少一个基本版本的免费下载,因此您也可以简单地尝试一下并体验一下这些选项。
其他 Apache 项目
无论您是使用捆绑的发行版还是坚持使用基本的 Apache Hadoop 下载,您都会遇到许多对其他相关 Apache 项目的引用。 我们已经在本书中介绍了 Hive、Sqoop 和 Flume;现在我们将重点介绍其他一些。
请注意,这篇报道试图指出亮点(从我的角度来看),并让人们品尝到可用项目的广泛类型。 就像以前一样,继续保持警惕;会有新的不断推出。
HBase
也许最受欢迎的 Apache Hadoop 相关项目是HBase;它的主页位于hbase.apache.org。 基于 Google 在一篇学术论文中公布的 Bigtable 数据存储模型(听起来熟悉吗?),HBase 是一个位于 HDFS 之上的非关系型数据存储。
MapReduce 和 Have 任务都专注于类似批处理的数据访问模式,而 HBase 则寻求提供非常低延迟的数据访问。 因此,与前面提到的技术不同,HBase 可以直接支持面向用户的服务。
HBase 数据模型不是我们在配置单元和所有其他 RDBMS 中看到的关系方法。 相反,它是一个键值、无模式的解决方案,采用面向列的数据视图;列可以在运行时添加,并取决于插入到 HBase 中的值。 因此,每个查找操作都非常快,因为它实际上是从行键到所需列的键值映射。 HBase 还将时间戳视为数据的另一个维度,因此可以直接从某个时间点检索数据。
数据模型非常强大,但并不适合所有用例,就像关系模型并不普遍适用一样。 但是,如果您需要存储在 Hadoop 中的大规模数据的结构化低延迟视图,HBase 绝对是您应该考虑的。
Oozie
我们已经说过很多次,Hadoop 集群不是生活在真空中,需要与其他系统集成,并集成到更广泛的工作流中。 Oozie可从Hadoop获得,它是一个专注于 oozie.apache.org 的工作流调度器,可以解决后一种情况。
在其最简单的形式中,Oozie 提供了基于基于时间的标准(例如,每小时执行一次)或数据可用性(例如,当新数据到达该位置时执行)来调度 MapReduce 作业执行的机制。 它允许规范能够描述完整的端到端流程的多阶段工作流。
除了简单的 MapReduce 作业,Oozie 还可以调度运行配置单元或 Pig 命令的作业,以及完全在 Hadoop 之外的任务(例如发送电子邮件、运行 shell 脚本或在远程主机上运行命令)。
构建工作流的方法有很多种; 常用的方法是使用Extract Transform 和****Load(ETL)工具,如Pentaho Kettle(kettle.pentaho.com)和Spring Batch(static.springsource.org/spring-batc…)。 例如,它们确实包括一些 Hadoop 集成,但传统的专用工作流引擎可能不包括。 如果您正在构建具有重要 Hadoop 交互的工作流,并且没有必须与之集成的现有工作流工具,那么可以考虑使用 Oozie。
旋转
当希望使用 Amazon AWS 等云服务进行 Hadoop 部署时,与在 EC2 上设置自己的群集相比,使用更高级别的服务(如 ElasticMapReduce)通常要容易得多。 尽管有脚本可以提供帮助,但事实是在云基础设施上基于 Hadoop 的部署可能会带来开销。 这就是whir.apache.org中的 apachewhir的用武之地。
Whir 并不关注 Hadoop;它关注的是独立于供应商的云服务实例化,Hadoop 就是其中的一个例子。 WHIR 提供了一种编程方式,可以在云基础设施上指定和创建基于 Hadoop 的部署,为您处理所有底层服务方面。 它以独立于提供者的方式完成这项工作,这样,一旦您在 EC2 上启动,您就可以使用相同的代码在另一个提供者(如 Rackspace 或 Eucalyptus)上创建相同的设置。 这使得供应商锁定-通常是云部署的一个问题-不再是问题。
惠尔还没有完全做到这一点。 如今,它可以创建的服务有限,并且只支持单一提供商 AWS。 但是,如果您对轻松部署云感兴趣,那么值得关注它的进展。
Mahout
前面的项目都是通用的,因为它们提供了独立于任何应用领域的功能。 ApacheMahout位于mahout.apache.org,它是构建在 Hadoop 和 MapReduce 之上的机器学习算法库。
Hadoop 处理模型通常非常适合机器学习应用,因为机器学习应用的目标是从大数据集中提取价值和意义。 Manhout 提供了集群和推荐器等常见 ML 技术的实现。
如果您有大量数据,并且需要帮助找到关键模式、关系,或者只是大海捞针,Mahout 可能会提供帮助。
MRUnit
我们将提到的最终 Apache Hadoop 项目还突出显示了可用内容的广泛范围。 在很大程度上,如果您的 MapReduce 作业经常由于潜在的 bug 而失败,那么使用多少很酷的技术以及使用哪个发行版都无关紧要。 最近从mrunit.apache.org升级的 MRUnit 可以在这方面提供帮助。
开发 MapReduce 作业可能很困难,尤其是在早期,但测试和调试它们几乎总是很困难的。 MRUnit 采用其同名产品(如 JUnit 和 DBUnit)的单元测试模型,并提供一个框架来帮助编写和执行测试,从而帮助提高代码质量。 构建一个测试套件、集成自动化测试和构建工具,突然之间,所有那些您在编写非 MapReduce 代码时做梦也不会想要遵循的软件工程最佳实践也都在这里提供了。
如果您曾经编写过 MapReduce 作业,那么 MRUnit 可能会让您感兴趣。 依我拙见,这是一个非常重要的项目,请检查一下。
其他编程抽象
Hadoop 不只是通过附加功能来扩展;有一些工具可以提供完全不同的范例来编写用于在 Hadoop 中处理数据的代码。
PIG
我们在第 8 章,A Relational View on Data with Have中提到了Pig(pig.apache.org),这里不再赘述。 请记住,它是可用的,如果您的流程或人员认为 Hadoop 流程的数据流定义比编写原始 MapReduce 代码或 HiveQL 脚本更直观或更适合,那么它可能会很有用。 请记住,主要区别在于 Pig 是一种命令式语言(它定义了流程将如何执行),而 Have 则更具声明性(定义了期望的结果,但不定义它们将如何产生)。
级联
Cascading不是一个 apache 项目,但它是开源的,可以从www.cascading.org获得。 虽然配置单元和 Pig 有效地定义了用来表示数据处理的不同语言,但级联提供了一组更高级别的抽象。
该模型不考虑多个 MapReduce 作业如何通过级联处理和共享数据,而是一个使用管道和多个连接器、分路器和类似构造的数据流。 这些都是以编程方式构建的(核心 API 最初是 Java,但还有许多其他语言绑定),级联管理集群上工作流的转换、部署和执行。
如果您想要一个更高级别的 MapReduce 接口,而 Pig 和 Have 的声明性样式不适合,那么级联的编程模型可能就是您想要的。
AWS 资源
许多 Hadoop 技术可以作为自我管理群集的一部分部署在 AWS 上。 但是,正如 Amazon 提供对 Elastic MapReduce 的支持一样,Elastic MapReduce 将 Hadoop 作为托管服务处理,还有一些其他服务值得一提。
电子病历上的 HBase
这本身并不是一个真正独特的服务,但就像 EMR 拥有对配置单元和 Pig 的原生支持一样,它现在也提供了对 HBase 集群的直接支持。 这是一个相对较新的功能,看看它在实践中的运行情况会很有趣;HBase 历来对网络和系统负载的质量非常敏感。
SimpleDB
Amazon SimpleDB(HBase)是一个提供类似 aws.amazon.com/simpledb 的数据模型的服务。 这实际上不是在 Hadoop 上实现的,但是我们将提到这项服务和下面的服务,因为如果您感兴趣的是类似 HBase 的数据模型,它们确实提供了值得考虑的托管替代方案。 这项服务已经有几年的历史了,并且非常成熟,有非常好理解的用例。
SimpleDB 确实有一些限制,特别是在表大小和需要手动对大型数据集进行分区方面,但是如果您需要在较小的卷上使用 HBase 类型的存储,那么它可能是一个很好的选择。 它也很容易设置,是尝试基于列的数据模型的一种很好的方式。
DynamoDB
来自 AWS 的较新的服务是DynamoDB,可从[aws.amazon.com/DynamoDB](aws.amazon.com/ dynamodb)获得。 尽管它的数据模型再次与 SimpleDB 和 HBase 非常相似,但它针对的是一种非常不同类型的应用。 SimpleDB 有相当丰富的搜索 API,但在大小方面非常有限,DynamoDB 提供了一个更受限制的 API,但具有几乎无限可伸缩性的服务保证。
DynamoDB 定价模型特别有趣;不是为托管服务的特定数量的服务器付费,而是分配一定的读/写容量,DynamoDB 管理满足该配置容量所需的资源。 这是一个有趣的发展,因为它是一个更纯粹的服务模型,其中交付所需性能的机制对服务用户是完全不透明的。 如果您需要比 SimpleDB 能够提供的数据存储规模大得多的数据存储,请考虑 DynamoDB,但一定要仔细考虑定价模型,因为调配过多的容量很快就会变得非常昂贵。
信息来源
你不仅仅需要新的技术和工具,不管它们有多酷。 有时,更有经验的人提供一点帮助就可以把你从困境中拉出来。 在这方面,您已经做了很好的介绍;Hadoop 社区在许多领域都非常强大。
源代码
有时很容易被忽视,但 Hadoop 和所有其他 Apache 项目毕竟是完全开源的。 实际的源代码是有关系统如何工作的信息的最终来源(请原谅双关语)。 当您遇到意外行为时,熟悉源代码并通过某些功能进行跟踪可能会提供大量信息,更不用说有帮助了。
邮件列表和论坛
几乎所有前面列出的项目和服务都有自己的邮件列表和/或论坛;请查看特定链接的主页。 如果使用亚马逊,请务必访问forums.aws.amazon.com上的亚马逊开发者论坛。
记住一定要仔细阅读发帖指南,了解期望的礼仪。 这些都是大量的信息来源,并且特定项目的开发人员经常访问这些列表和论坛。 期待在 Hadoop 列表上看到核心 Hadoop 开发人员,在 Have 列表上看到 Have 开发人员,在 EMR 论坛上看到 EMR 开发人员,等等。
LinkedIn 群
在专业的社交网络 LinkedIn 上有个 Hadoop 和相关的群组。 搜索您感兴趣的特定领域,但一个好的起点可能是位于www.linkedin.com/groups/Hado…的一般 Hadoop 用户组。
拥抱
如果您想要更多面对面的互动,请在您所在的地区寻找Hadoop 用户组(Hug);大多数用户应该在wiki.apache.org/hadoop/Hado…上列出。 这些公司倾向于安排半定期的聚会,包括高质量的演示、与志同道合的人讨论技术的能力,以及经常是披萨和饮料。
你住的地方附近没有拥抱吗? 考虑开一家吧!
会议
虽然 Hadoop 是一项相对较新的技术,但已经有了一些涉及开源、学术和商业世界的重要会议活动。 像Hadoop Summit这样的活动相当大;它和其他活动通过wiki.apache.org/hadoop/Conf…链接。
摘要
在本章中,我们简要介绍了更广泛的 Hadoop 生态系统。 我们了解了 Hadoop 中即将发生的变化,特别是 HDFS 高可用性和 YILE,为什么会存在其他 Hadoop 发行版以及一些更受欢迎的发行版,以及其他提供功能、扩展或 Hadoop 支持工具的 Apache 项目。
我们还研究了编写或创建 Hadoop 作业和信息源的替代方法,以及如何与其他爱好者联系。
现在去享受乐趣,创造一些令人惊叹的东西吧!