如何将日志文件和二进制文件快速导入HDFS?

日志数据在应用程序中一直很常见,Hadoop能够处理生产系统生成的大量日志数据,比如网络设备、操作系统、Web服务器和应用程序的日志数据。这些日志文件提供了对系统和应用程序运行以及使用的见解,统一日志文件的原因是它们往往采用文本形式和面向行的方式,因此易于处理。

在《Hadoop从入门到精通》大型专题的上一章节中,我们介绍了可用于将数据复制到Hadoop的低级方法。本节不使用这些方法构建数据移动工具,而是介绍一些更高级别的工具,简化将日志和二进制数据移动到Hadoop的过程。类似Flume,Sqoop和Oozie这样的工具提供了定期(或连续)将数据从各种数据源(如文件,关系数据库和消息传递系统)移动到Hadoop的机制,并逐渐解决了整个过程中的诸多难题,让我们看看Flume如何将日志文件移入HDFS。

(注:本文为《Hadoop从入门到精通》大型专题的第五章内容,其他文章见文末链接,专题的上半部也将于不久之后与大家见面,请持续关注本专题!)

首选数据移动方法

如果在旧版Hadoop环境中运行,我们可能需要一些工具来移动数据,这些工具都会在本章介绍。如果使用Kafka作为数据传输机制,则允许将生产者与消费者分离,同时使多个消费者能够以不同的方式对数据进行操作。在这种情况下,我们可以使用Kafka在Hadoop上存储数据,并为实时数据流系统(如Storm或Spark Streaming)提供数据,然后使用它执行近实时计算。比如,Lambda架构允许以小增量实时计算聚合数据,并使用批处理层执行纠错和添加新数据点等,从而发挥实时和批处理系统的优势 。

实践:使用Flume将系统日志消息推送到HDFS

面对跨多个服务器的多个应用程序和系统生成的一堆日志文件,我们可能手忙脚乱。毫无疑问,从这些日志中可以挖掘出有价值的信息,但第一大挑战是将这些日志移动到Hadoop集群以便可以执行某些分析。

版本注意事项

此处的Flume使用版本1.4。与所有软件一样,不保证此处介绍的技术,代码和配置可以使用不同版本的Flume开箱即用。此外,Flume 1.4需要一些更新才能使其与Hadoop 2一起使用。

问题

希望将所有生产服务器的系统日志文件推送到HDFS。

解决方案

使用Flume(一种数据收集系统)将Linux日志文件推送到HDFS。

讨论

Flume的核心是日志文件收集和分发,收集系统日志并传输到HDFS。此技术的第一步涉及捕获附加到/var/log/messages的所有数据并将其传输到HDFS。我们将运行一个Flume agent(稍后详细介绍),这将完成所有工作。

Flume agent需要配置文件指明该做什么,以下代码为用例定义了一个:

要让示例起作用,需要确保正在使用可以访问Hadoop集群的主机,以及 HADOOP_HOME配置正确,还需要下载并安装Flume并将FLUME_HOME设置为指向安装目录。

使用文件名tail-hdfspart1.conf将前面的文件复制到Flume conf目录中。完成后,就可以启动Flume agent实例了:

这应该会产生很多输出,但最终应该看到类似于以下的输出,表明一切都好了:

此时,应该看到HDFS中出现的一些数据:

.tmp后缀表示Flume打开文件并继续写入。一旦完成,这将重命名文件并删除后缀:

可以捕获此文件以检查其内容,内容应与tail/var/log/messages对齐。

到目前为止,我们已经用Flume完成了第一次数据移动!

解析Flume agent

让我们回过头来检查一下做了什么。主要有两个部分:定义Flume配置文件,以及运行Flume agent。Flume配置文件包含有关源,通道和接收器的详细信息,这些都是影响Flume数据流不同部分的概念。图5.4显示了Flume agent中的这些概念。

让我们逐步介绍这些概念,包括用途以及工作原理。

Sources

Flume sources负责从外部客户端或其他Flume接收器读取数据。Flume中的数据单元被定义为一个事件,本质上是一个有效载荷和可选元数据集。Flume源将这些事件发送到一个或多个Flume通道,这些通道处理存储和缓冲。

图5.4 agent上下文中的Flume组件说明

Flume有一组广泛的内置源,包括HTTP,JMS和RPC。让我们来看看你设置的特定于源的配置属性:

exec source允许执行Unix命令,标准输出中发出的每一行都被捕获为事件(默认情况下会忽略常见错误)。在前面的示例中,tail -F命令用于在生成系统消息时捕获它们。如果可以更好地控制文件(例如,如果可以在完成所有写入后将它们移动到目录中),考虑使用Flume的假脱机目录源(称为spooldir),因为它提供了exec source无法获得的可靠性语义。

仅使用tail进行测试

不鼓励使用tail进行测试以外的任何操作。

此配置中突出显示的另一个功能是拦截器,它允许向事件添加元数据。回想一下,HDFS中的数据是根据时间戳组织的:第一部分是日期,第二部分是时间:

之所以能这样做,是因为使用时间戳拦截器修改了每个事件,时间戳拦截器将源处理事件的时间(以毫秒为单位)插入到事件头。然后,Flume HDFS接收器使用此时间戳来确定事件写入位置。

为了总结Flume sources,让我们介绍一下其提供的功能:

  • 事务语义,允许以至少一次语义可靠地移动数据,并非所有数据源都支持此功能。
  • 拦截器,提供修改或删除事件的功能。对于使用主机,时间和唯一标识符来注释事件非常有用,这对于重复数据删除非常有用。
  • 选择器,允许以各种方式扇出或多路复用事件,可以通过将事件复制到多个通道来扇出事件,也可以根据事件头将事件路由到不同通道。

通道

Flume通道在agent内部提供数据存储设施。源将事件添加到通道,并从通道中删除事件。Flume内部的通道提供高可用性,可以根据应用所需的容量和吞吐量选择。

Flume捆绑了三个通道:

  • 内存通道将事件存储在内存队列中。这对于高吞吐数据流非常有用,但其没有持久性保证,这意味着如果agent发生故障,用户将丢失数据。
  • 文件通道将事件持久保存到磁盘。该实现使用高效的日志并具有强大的持久性。
  • JDBC通道将事件存储在数据库中。这提供了最强的可用性和可恢复性,但是以性能为代价。

在前面的示例中,我们使用了内存通道,并将其存储事件数限制为100,000。一旦内存通道达到最大事件数,将开始拒绝来自源的其他请求以添加更多事件。根据源的类型,这意味着源将重试或删除事件(exec源将丢弃事件):

Sinks

Flume接收器从一个或多个Flume通道中接收事件,并将这些事件转发到另一个Flume源(在多hop流程中),或以特定于接收器的方式处理事件。Flume内置了许多接收器,包括HDFS,HBase,Solr和Elasticsearch。

在前面的示例中,我们将流配置为使用HDFS接收器:

我们将接收器配置为根据时间戳写入文件(请注意%y和其他时间戳别名)。我们可以这样做,因为使用exec源中的时间戳拦截器标记事件。实际上,可以使用任何header值来确定事件输出位置(例如,可以添加主机拦截器,然后根据生成事件的主机来写入文件)。

可以通过各种方式配置HDFS接收器,以确定文件的滚动方式。当接收器读取第一个事件时,它将打开一个新文件(如果尚未打开)并写入该文件。默认情况下,接收器将继续保持文件打开并将事件写入其中,大约需要30秒,之后文件将被关闭,可以使用表5.5中的属性更改滚动行为。

表5.5 Flume HDFS接收器的rollover属性

默认HDFS接收器设置不应在生产中使用,因为它们会导致大量可能很小的文件。建议升级value或使用下游压缩作业来合并这些小文件。

HDFS接收器允许指定在写入文件时如何序列化事件。默认情况下,它们以文本格式序列化,没有拦截器添加任何header。 例如,如果要在Avro中写入数据(也包括事件头),则可以使用序列化程序配置来执行此操作。这样做时,还可以指定Avro内部用于压缩数据的Hadoop压缩编解码器:

总结

Flume中的可靠性取决于使用的通道类型,数据源是否具有重新传输事件的能力,以及是否将事件多路复用到多个源以减轻不可恢复的节点故障。在该技术中,使用了存储器通道和执行器源,但是在面对故障时都不提供可靠性。添加可靠性的一种方法是用假脱机目录源替换exec源,并用磁盘通道替换内存通道。

我们可以使用单个源,通道和接收器运行单个agent的单台计算机上使用Flume,但Flume可以支持完全分布式设置,可以在多个主机上运行agent,在源和最终目标之间有多个agent hop。图5.5显示了Flume如何在分布式环境中运行。

此技术的目标是将数据移动到HDFS中。但是,Flume可以支持各种数据接收器,包括HBase,文件roll,Elasticsearch和Solr。使用Flume写入Elasticsearch或Solr可实现强大的近实时索引。

因此,Flume是一个非常强大的数据移动工具,可以轻松支持将数据移动到HDFS以及许多其他位置。它可以持续移动数据并支持各种级别的弹性,以解决系统故障,这是一个只需简单配置就可运行的系统。

图5.5 使用负载平衡和 fan-in将log4j日志移动到HDFS的Flume设置

Flume没有真正优化的是使用二进制数据。它可以支持移动二进制数据,但会将整个二进制事件加载到内存中,因此移动大小为GB或更大的文件将无法正常工作。

实践:一种将文件复制到HDFS的自动机制

你可能已经学会了如何使用像Flume这样的日志收集工具自动将数据移动到HDFS中。但是,这些工具不支持使用半结构化或二进制数据输出。在该实践中,我们将了解如何自动将这些文件移动到HDFS中。

企业实际生产环境通常具有网络孤岛,Hadoop集群可以远离其他生产应用程序进行细分。在这种情况下,Hadoop集群可能无法从其他数据源提取数据,因此无需将数据推送到Hadoop。

需要一种机制来自动化将任何格式的文件复制到HDFS的过程,类似于Linux工具rsync。该机制应该能够压缩用HDFS编写的文件,并提供一种动态确定HDFS目的地的方法以进行数据分区。

现有的文件传输机制,如Flume,Scribe和Chukwa,都是为了支持日志文件。如果文件格式不同,例如semistructured或binary,该怎么办?如果文件以Hadoop从属节点无法直接访问的方式被孤立,那么也无法使用Oozie来帮助进行文件输入。

问题

需要自动执行将远程服务器上的文件复制到HDFS的过程。

解决方案

开源HDFS File Slurper项目可以将任何格式的文件复制到HDFS或从中复制出来。该技术涵盖了如何配置和使用它来将数据复制到HDFS中。

讨论

可以使用HDFS File Slurper来帮助实现自动化(https://github.com/alexholmes/hdfs-file-slurper)。HDFS File Slurper是一个简单的实用程序,支持将文件从本地目录复制到HDFS,反之亦然。

图5.6提供了Slurper的高级概述,以及如何使用它来复制文件的示例。Slurper读取源目录中存在的所有文件,并可选择查询脚本以确定目标目录中的文件位置。然后,它将文件写入目标,之后有一个可选的验证步骤。在成功完成所有步骤后,Slurper将源文件移动到对应文件夹。

图5.6 用于复制文件的HDFS File Slurper数据流

使用这种技术,需要确保解决以下几个挑战:

  • 如何有效地将写入分区到HDFS,以便不将所有内容整合到一个目录?
  • 如何确定HDFS中的数据是否已准备好进行处理(以避免读取中间复制的文件)?
  • 如何自动定期执行实用程序?

第一步是从https://github.com/alexholmes/hdfs-file-slurper/releases下载最新的HDFS File Slurper tarball,并将其安装在可以访问Hadoop集群和本地Hadoop安装的主机上:

组件

在运行代码之前,需要编辑/usr/local/hdfs-slurper/conf/slurper-env.sh并设置hadoop脚本的位置。以下代码是slurper-eng.sh文件的示例,如果遵循Hadoop安装说明:

Slurper捆绑了/usr/local/hdfs-slurper/conf/slurper.conf文件,其中包含源和目标目录的详细信息以及其他选项。该文件包含以下默认设置,你可以更改:

让我们仔细看看这些设置:

  • DATASOURCE_NAME—指定要传输的数据名称。当通过Linux init守护程序管理系统启动时,该名称用于日志文件名。
  • SRC_DIR—指定源目录。移动到此处的任何文件都会自动复制到目标目录(使用中间hop到目标目录)。
  • WORK_DIR—这是工作目录。在复制到目标之前,源目录中的文件将移动到此处。
  • COMPLETE_DIR—指定完整目录。复制完成后,文件将从工作目录移动到此目录中。或者,可以使用--remove-after-copy选项删除源文件,在这种情况下,不应提供--complete-dir选项。
  • ERROR_DIR—这是错误目录。复制期间遇到的任何错误都会导致源文件移动到此目录中。
  • DEST_DIR—设置源文件的最终目标目录。
  • DEST_STAGING_DIR—指定目标目录。首先将文件复制到此目录中,一旦复制成功,Slurper就会将副本移动到目标位置,以避免目标目录包含部分写入文件(如果发生故障)。

你会注意到所有目录名称都是HDFS URI。HDFS以这种方式区分不同的文件系统。file:/URI本地文件系统上的路径,hdfs:/URI表示HDFS中的路径。事实上,只要正确配置Hadoop,Slurper就支持任何Hadoop文件系统。

运行

创建一个名为/tmp/slurper/in的本地目录,在其中写入一个空文件,然后运行Slurper:

Slurper设计的一个关键特性是不能与部分写入文件一起使用。文件必须以原子方式移动到源目录中(Linux和HDFS文件系统中的文件移动都是原子的)。或者,可以写入以句点(.)开头的文件名,Slurper会忽略该文件名,文件写入完成后,可以将文件重命名为不带句点前缀的名称。

请注意,复制具有相同文件名的多个文件将导致目标被覆盖,用户有责任确保文件是唯一的,以防止这种情况发生。

动态目标路由

如果每天将少量文件移动到HDFS中,则上一种方法很有效。但是,如果正在处理大量文件,你会想到将它们分成不同的目录。这样做的好处是可以对MapReduce作业的输入数据进行更细粒度的控制,并有助于在文件系统中整体组织数据(如果不希望计算机上的所有文件都在单个目录)。

如何对目标目录和Slurper使用的文件名进行更多动态控制?Slurper配置文件具有SCRIPT选项(与DEST_DIR选项互斥),可以在其中指定一个脚本,该脚本提供源文件到目标文件的动态映射。

假设正在使用的文件包含文件名中的日期,并且已决定要按日期在HDFS中组织数据。那么,可以编写脚本来执行此映射活动。以下示例是执行此操作的Python脚本:

现在可以更新/usr/local/hdfs-slurper/conf/slurper.conf,设置SCRIPT,并注释掉DEST_DIR,这会在文件中生成以下条目:

如果再次运行Slurper,会注意到目标路径现在由Python脚本按日期分区:

数据压缩和验证

如果要在HDFS中压缩输出文件并验证副本是否正确,该怎么办?需要使用COMPRESSION_CODEC选项,其值是实现CompressionCodec接口的类。如果压缩编解码器是LZO或LZOP,还可以添加CREATE_LZO_INDEX选项,以便创建LZOP索引。 (具体内容请阅读第四章,链接见文末)

验证功能会在复制完成后重新读取目标文件,并确保目标文件的校验和与源文件匹配。这导致处理时间更长,但增加了复制成功的额外保证。

以下配置片段显示了LZOP编解码器,LZO索引和启用的文件验证:

让我们再次运行Slurper:

连续运转

现在,你已经掌握了基本机制,最后一步是将该工具作为守护程序运行,以便不断查找要传输的文件。为此,可以使用名为bin/slurper-inittab.sh的脚本,该脚本旨在与inittab respawn一起使用。

此脚本不会创建PID文件或执行nohup-在respawn的上下文中都没有意义,因为inittab正在管理进程。使用DATASOURCE_NAME配置值来创建日志文件名,这意味着可以使用记录到不同日志文件的不同配置文件来启动多个Slurper实例。

总结

Slurper是一个很方便的工具,用于从本地文件系统到HDFS的数据输入,还通过从HDFS复制到本地文件系统来支持数据输出。在MapReduce无法访问文件系统并且正在传输的文件形式不适用于Flume等工具的情况下,它非常有用。

实践:使用Oozie安排定期数据提取

如果数据位于文件系统、Web服务器或可从Hadoop集群访问的任何其他系统上,我们将需要一种定期将该数据提取到Hadoop的方法。目前,有一些推送日志文件和从数据库中提取的工具可供选择,但如果需要与其他系统进行交互,则可能需要自己处理数据输入过程。

此技术使用Oozie 4.0.0版。

此数据入口分为两部分:将数据从另一系统导入Hadoop以及定期进行数据传输。

问题

自动执行每日任务,以将内容从HTTP服务器下载到HDFS。

解决方案

Oozie可用于将数据移动到HDFS,还可用于执行发布,例如启动MapReduce作业以处理获取的数据。Oozie现在是Apache项目,管理数据处理活动的Hadoop工作流引擎。Oozie还有一个协调器引擎,可以根据数据和时间触发器启动工作流程。

讨论

在此实践中,我们将每24小时从多个URL执行下载,使用Oozie管理工作流程和日程安排。该技术的流程如图5.7所示,我们将使用Oozie触发功能每24小时启动一次MapReduce作业。

图5.7 Oozie技术的数据流

第一步是查看协调器XML配置文件。Oozie的协调引擎使用此文件来确定何时应启动工作流程。Oozie使用模板引擎和表达式语言来执行参数化,如下代码所示。使用以下内容创建名为coordinator.xml的文件:

代码5.1 使用模板引擎通过Oozie执行参数化

Oozie调度可能会让人困惑的是,开始和结束时间与作业执行的实际时间无关。相反,它们指的是每个工作流程执行创建的日期,这在定期生成数据并且希望能够及时返回某个点并对该数据执行某些操作的情况下非常有用。在这个例子中,你希望每24小时执行一份工作。所以,你可以将开始日期设置为昨天,将结束日期设置为将来的某个日期。

接下来,我们需要定义实际工作流程,该工作流程将在每个固定时间间隔执行,并且在到达间隔时继续执行。为此,创建一个名为workflow.xml的文件,其中包含下一个代码中显示的内容。

代码5.2 使用Oozie协调器定义工作流程

Oozie希望map和reduce类使用“旧的”MapReduce API。如果要使用“新”API,则需要指定其他属性:

最后一步是定义属性文件,该文件指定如何获取HDFS,MapReduce以及之前在HDFS中标识的两个XML文件的位置。创建一个名为job.properties的文件,如以下代码所示:

不同Hadoop版本的JobTracker属性

如果使用Hadoop 1.X版本,则应使用jobTracker属性中的JobTracker RPC端口(默认值为8021)。否则使用YARN ResourceManager RPC端口(默认为8032)。

在上一个代码段中,HDFS中的位置指示本章前面编写的coordinator.xml和workflow.xml文件的位置。现在,需要将XML文件,输入文件和包含MapReduce代码的JAR文件复制到HDFS中:

最后,在Oozie中运行作业:

可以使用作业ID获取有关作业的一些信息:

此输出导致作业的一次运行,可以看到运行时间。整体状态为RUNNING,这意味着作业正在等待下一个间隔发生。当整个作业完成时(到结束日期之后),状态将转换为SUCCEEDED。

可以确认HDFS中的输出目录对应于具体日期:

只要作业正在运行,它将继续执行直到日期结束,在此示例中已将其设置为2026年。如果要停止作业,请使用-suspend选项:

Oozie还可以分别使用-resume和-kill选项恢复暂停的作业以及杀死工作流程。

总结

我展示了使用Oozie协调器的一个示例,它提供了类似cron的功能来启动定期Oozie工作流程。Oozie协调器还可用于根据数据可用性触发工作流(如果没有可用数据,则不会触发工作流)。例如,如果有一个外部流程,甚至MapReduce定期生成数据,就可以使用Oozie的数据驱动协调器来触发工作流,该工作流可以聚合或处理数据。

本节,我们介绍了三种可用于数据导入的自动机制。第一种是Flume,用于将日志数据传输到Hadoop的强大工具,第二种是HDFS File Slurper,它可以自动化将数据推送到HDFS。最后研究了Oozie如何用于定期启动MapReduce作业以将数据导入HDFS或MapReduce。

在探索数据输入上,我们研究了推送日志文件,从常规文件系统推送文件以及从Web服务器中提取文件。大多数企业都会感兴趣的一大数据源是位于OLTP数据库中的关系数据。在本章接下来的几篇文章中,我将分享如何访问关系数据。

你可能感兴趣的:(大数据,数据库,python)