分析和优化云集群性能
 

2011-06-02 来源:ibm

 

简介

Hadoop 是一个灵活的开放源码 Java 框架,用于在一般硬件网络上执行大规模数据处理。它的思想来源于最初由 Google Labs 开发的 MapReduce 和 Global File System (GFS) 技术,由于具有高效、可靠和可伸缩的优点,它越来越流行了。Hadoop 现在是顶级 Apache 项目,IBM、Google、Yahoo! 和 Facebook 等许多公司都支持和使用 Hadoop,它已经成为大规模数据处理方面事实上的行业标准框架。

Hadoop 对于云计算意味着什么?云计算的目的之一是,以尽可能低的开销为计算机资源提供高可用性。Hadoop 能够处理数千个节点和 PB 量级的数据,可以自动地处理作业调度、部分失败和负载平衡,因此它是实现这个目标的完美工具。

要想充分使用计算机资源,优化性能是非常重要的,包括 CPU、内存和 I/O(磁盘和网络)。Hadoop 可以自动地改进性能,同时向用户提供接口,让他们可以针对自己的应用程序优化性能。本文介绍重要的 Hadoop 可配置参数以及分析和调优性能的方法。

建立环境

部署 Hadoop 环境的步骤

在执行性能调优之前,需要先构建 Hadoop 集群环境。步骤如下:

准备集群节点,在这些节点上安装 Linux OS、JDK 1.6 和 ssh。确保每个节点上都在运行 sshd。

访问 The Apache Software Foundation 站点,下载稳定的 Hadoop 发行版。

选择自己的 NameNode (NN)、JobTracker (JT) 和 Secondary NameNode (SNN);其他节点是 DataNode (DN) 和 TaskTracker (TT)。本文假设选择 host001 作为 NN,host002 作为 JT,host003 作为 SNN。

让 NN、JT 和 SNN 能够通过 ssh 无需密码地访问所有 DN 和 TT。

在每个节点上解压下载的 Hadoop 发行版;下面使用 $HADOOP_HOME 代表解压位置。

在 NN 上,进入 $HADOOP_HOME 目录并修改配置文件。

把 host003 添加到 $HADOOP_HOME/conf/masters 中。

把所有 DN/TT 节点的 IP 地址/主机名添加到 $HADOOP_HOME/conf/slaves 中,每个主机一行。 注意:如果使用主机名,就需要通过配置 /etc/hosts 文件确保集群中的所有节点都知道每个主机名。

把以下属性添加到 $HADOOP_HOME/conf/core-site.xml 中以设置 NN IP/端口:

<property>

<name>fs.default.name</name>

<value>hdfs://host001:9000</value>

</property>

把以下属性添加到 $HADOOP_HOME/conf/mapred-site.xml 中以设置 JT IP/端口:

<property>

<name> mapred.job.tracker </name>

<value>host002:9001</value>

</property>

注意:如果使用 Hadoop 0.21.0,这个属性名应该是 mapreduce.jobtracker.address。

如果在 NN 上有多个网络接口,那么把以下属性添加到 $HADOOP_HOME/conf/hdfs-site.xml 中:

<property>

<name>dfs.datanode.dns.nameserver</name>

<value>eth1</value>

<description>The name of the Network Interface from which a data node

should report its IP address.

</description>

</property>

把上面提到的所有配置文件从 NN 复制到集群中所有其他节点上的 $HADOOP_HOME/conf/ 目录中。

在 NN 上进入 $HADOOP_HOME/bin 目录。

使用 $./hadoop namenode -format 命令格式化 NN。

启动 start-all.sh 脚本以启动 Hadoop 守护进程。

更详细的信息参见 Hadoop Common。注意:如果选用 Hadoop 0.21.0,那么必须使用当前的 JDK(由 JIRA HADOOP-6941 跟踪)。

安装并配置 nmon 性能监视工具

nmon 是一个系统管理、调优和基准测试工具,可以简便地监视大量重要的性能信息。可以在整个性能调优过程中使用 nmon 作为监视工具。按以下步骤安装并配置 nmon,建立自己的性能监视系统:

从 nmon for Linux 站点下载 nmon 二进制包。找到适合您的 Linux OS 的版本,把它复制到 Hadoop 集群的所有节点。下面使用 $NMON_HOME 代表放置 nmon 二进制代码的位置。

因为已经让 NN、JT 和 SNN 能够通过 ssh 无需密码地访问所有其他节点,而且将在 JT 上提交所有 map/reduce 作业,所以选择 JT 作为中心节点收集所有 nmon 数据。登录 JT 节点,然后执行以下步骤。

使用以下命令在 JT (host002) 上创建一个目录(例如 /home/hadoop/perf_share)并通过 NFS 共享它:

创建目录:$mkdir /home/hadoop/perf_share

修改 /etc/exports 文件,在其中包含以下行:/home/hadoop/perf_share *(rw,sync)

重新启动 NFS 服务:$/etc/rc.d/init.d/nfs restart

在所有其他节点上创建这个目录并把它们挂装到 JT 上的 perf_share 目录:

$mkdir/home/hadoop/perf_share

$mount host002: /home/hadoop/perf_share /home/hadoop/perf_share

创建以下脚本以便在所有节点上启动 nmon:

hosts=( shihc008 shihc009 shihc010 shihc011 shihc012 shihc013 shihc014 shihc015

shihc016 shihc017)

# Remove all data in /home/hadoop/perf_share

for host in ${hosts[@]}

do

ssh $host "cd /home/hadoop/perf_share;rm -rf *"

done

# Start nmon on all nodes

for host in ${hosts[@]}

do

ssh $host " /usr/bin/nmon -f -m /home/hadoop/perf_share -s 30 -c 360"

done

在最后的 nmon 命令中,-f 表示希望把数据保存到文件中,并不在屏幕上显示;-m 表示保存数据的位置;-s 30 表示希望每 30 秒捕捉一次数据;-c 360 表示需要 360 个数据点(即快照),总数据收集时间为 30x360 秒,即 3 小时。

从 nmonanalyser wiki 下载 nmonanalyser(这个 Excel 电子表格接受 nmon 的输出文件,生成一些漂亮的图表以帮助分析),用它分析收集到的监视数据。

Hadoop 可配置参数

Hadoop 提供许多配置选项,用户和管理员可以通过它们进行集群设置和调优。core/hdfs/mapred-default.xml 中有许多变量,可以在 core/hdfs/mapred-site.xml 中覆盖它们。一些变量指定系统上的文件路径,而其他变量对 Hadoop 的内部进行深入的调整。

性能调优主要有四个方面:CPU、内存、磁盘 I/O 和网络。本文介绍与这四个方面最相关的参数,您可以使用后面介绍的方法研究 *-default.xml 中的其他参数。

与 CPU 相关的参数: mapred.tasktracker.map 和 reduce.tasks.maximum

决定由任务跟踪器同时运行的 map/reduce 任务的最大数量。这两个参数与 CPU 利用率最相关。这两个参数的默认值都是 2。根据集群的具体情况适当地增加它们的值,这会提高 CPU 利用率,由此提高性能。例如,假设集群中的每个节点有 4 个 CPU,支持并发多线程,每个 CPU 有两个核;那么守护进程的总数不应该超过 4x2x2=16 个。考虑到 DN 和 TT 要占用两个,map/reduce 任务最多可以占用 14 个,所以这两个参数最合适的值是 7。

在 mapred-site.xml 中设置此参数。

与内存相关的参数: mapred.child.java.opts

这是用于 JVM 调优的主要参数。默认值是 -Xmx200m,这给每个子任务线程分配最多 200 MB 内存。如果作业很大,可以增加这个值,但是应该确保这不会造成交换,交换会严重降低性能。

我们来研究一下这个参数如何影响总内存使用量。假设 map/reduce 任务的最大数量设置为 7,mapred.child.java.opts 保持默认值。那么,正在运行的任务的内存开销为 2x7x200 MB =2800 MB。如果每个工作者节点都有 DN 和 TT 守护进程,每个守护进程在默认情况下占用 1 GB 内存,那么分配的总内存大约为 4.8 GB。

在 mapred-site.xml 中设置此参数。

与磁盘 I/O 相关的参数: mapred.compress.map.output、mapred.output.compress 和 mapred.map.output.compression.codec

这些参数控制是否对输出进行压缩,其中 mapred.compress.map.output 用于 map 输出压缩,mapred.output.compress 用于作业输出压缩,mapred.map.output.compression.codec 用于压缩代码。这些选项在默认情况下都是禁用的。

启用输出压缩可以加快磁盘(本地/Hadoop Distributed File System (HDFS))写操作,减少数据传输的总时间(在 shuffle 和 HDFS 写阶段),但是在另一方面压缩/解压过程会增加开销。

根据个人经验,启用压缩对于使用随机键/值的操作序列是无效的。建议只在处理大量有组织的数据(尤其是自然语言数据)时启用压缩。

在 mapred-site.xml 中设置这些参数。

io.sort.mb 参数

这个参数设置用于 map 端排序的缓冲区大小,单位是 MB,默认值是 100。这个值越大,溢出到磁盘就越少,因此会减少 map 端的 I/O 时间。注意,增加这个值会导致每个 map 任务需要的内存增加。

根据个人经验,在 map 输出很大而且 map 端 I/O 很频繁的情况下,应该尝试增加这个值。

在 mapred-site.xml 中设置此参数。

io.sort.factor 参数

这个参数设置在 map/reduce 任务中同时合并的输入流(文件)数量。这个值越大,溢出到磁盘就越少,因此会减少 map/reduce 的 I/O 时间。注意,如果给每个任务分配的内存不够大,增加这个值可能会导致更多垃圾收集活动。

根据个人经验,如果出现大量溢出到磁盘,而且排序和 shuffle 阶段的 I/O 时间很高,就应该尝试增加这个值。

在 mapred-site.xml 中设置此参数。

mapred.job.reduce.input.buffer.percent 参数

这个参数设置用于在 reduce 阶段保存 map 输出的内存的百分比(相对于最大堆大小),默认值是 0。当 shuffle 结束时,内存中剩余的 map 输出必须少于这个阈值,然后 reduce 阶段才能够开始。这个值越大,磁盘上的合并就越少,因此会减少 reduce 阶段本地磁盘上的 I/O 时间。注意,如果给每个任务分配的内存不够大,增加这个值可能会导致更多垃圾收集活动。

根据个人经验,如果 map 输出很大而且在 reduce 到排序阶段本地磁盘 I/O 很频繁,应该尝试增加这个值。

在 mapred-site.xml 中设置此参数。

mapred.local.dir 和 dfs.data.dir 参数

这两个参数决定把 Hadoop 中的数据放在什么地方,mapred.local.dir 决定存储 MapReduce 中间数据( map 输出数据)的位置,dfs.data.dir 决定存储 HDFS 数据的位置。

根据个人经验,把这些位置分散在每个节点上的所有磁盘上可以实现磁盘 I/O 平衡,因此会显著改进磁盘 I/O 性能。

在 mapred-site.xml 中设置 mapred.local.dir,在 hdfs-site.xml 中设置 dfs.data.dir。

与网络相关的参数: topology.script.file.name

这个参数指向一个用户定义的脚本,这个脚本判断机架-主机(rack-host)映射以配置机架感知。在 core-site.xml 文件中设置此参数。

机架感知是对于提高网络性能最重要的配置,强烈建议按

http://hadoop.apache.org/common/docs/current/cluster_setup.html#Hadoop+Rack+Awareness 和

http://wiki.apache.org/hadoop/topology_rack_awareness_scripts 上的说明配置它。

mapred.reduce.parallel.copies 参数

这个参数决定把 map 输出复制到 reduce 所使用的线程数量,默认值是 5。增加这个值可以提高网络传输速度,加快复制 map 输出的过程,但是也会增加 CPU 使用量。

根据个人经验,增加这个值的效果不太明显,建议只在 map 输出非常大的情况下增加这个值。

注意:上面列出的参数名都是 Hadoop 0.20.x 中的;如果使用 0.21.0,名称可能有变化。除了 Hadoop 参数之外,还有一些会影响

体性能的系统参数,比如机架间带宽。

如何调优和提高性能

介绍了上面的预备知识之后,现在讨论如何调优和提高性能。可以把整个过程划分为以下步骤。

步骤 1:选择测试基准

整个 Hadoop 集群的性能由两个方面决定:HDFS I/O 性能和 MapReduce 运行时性能。Hadoop 本身提供几个基准,比如用于 HDFS I/O 测试的 TestDFSIO 和 dfsthroughput(包含在 hadoop-*-test.jar 中)、用于总体硬件测试的 Sort(包含在 hadoop-*-examples.jar 中)和 Gridmix(它模拟网格环境中的混合工作负载,放在 $HADOOP_HOME/src/benchmarks 目录中)。可以根据自己的测试需求选择任何基准。

在所有这些基准中,当输入数据很大时,Sort 可以同时反映 MapReduce 运行时性能(在 “执行排序” 过程中)和 HDFS I/O 性能(在 “把排序结果写到 HDFS” 过程中)。另外,Sort 是 Apache 推荐的硬件基准。(可以通过 Hadoop Wiki 找到相关信息。)因此,本文使用 Sort 作为示例测试基准讲解性能调优方法。

步骤 2:构建基线

测试环境:

基准:Sort

输入数据规模:500 GB

Hadoop 集群规模:10 个 DN/TT 节点

所有节点都是相同类型的

节点信息:

Linux OS

两个 4 核处理器,支持并发多线程

32 GB 内存

5 个 500 GB 磁盘

测试脚本:下面是测试使用的脚本(关于运行 Sort 基准的更多信息参见 Hadoop Wiki)。所有脚本都应该在 JT 节点上运行。

注意:把上面提到的 start_nmon.sh 脚本和以下脚本放在存储测试结果的目录中。

baseline_test.sh

run_sort_baseline.sh

基线测试使用的参数值:

Hadoop 参数值:

mapred.tasktracker.map.tasks.maximum = 2 (默认值)

mapred.tasktracker.reduce.tasks.maximum = 2 (默认值)

mapred.reduce.parallel.copies = 5 (默认值)

mapred.child.java.opts = -Xmx200m (默认值)

mapred.job.reduce.input.buffer.percent = 0 (默认值)

io.sort.mb = 100 (默认值)

io.sort.factor = 10 (默认值)

mapred.local.dir = /hadoop/sdb

dfs.data.dir = /hadoop/sdc, /hadoop/sdd, /hadoop/sde

系统参数值:

机架间带宽 = 1 Gb

基线测试结果:

执行时间:10051 秒

资源使用量汇总:

详细的图表:

获得所有 nmon 数据之后,可以使用 nmonanalyser 生成图表。因为 nmonanalyser 是一个 Excel 电子表格,所以只需打开它,单击 analyse nmon data,选择 nmon 文件。然后就可以得到经过分析的图表。

图 1. 使用 nmonanalyser 分析 nmon 数据

nmonanalyser 对于基线测试生成的详细图表如下:

图 2. NameNode 图表

图 3. JobTracker 图表

图 4. DataNode/TaskTracker 图表

步骤 3:寻找瓶颈

需要根据监视数据和图表仔细地研究系统瓶颈。因为主要的工作负载分配给 DN/TT 节点,所以应该首先观察 DN/TT 节点的资源使用量(下面只给出 DN/TT 节点的 nmon 图表以节省篇幅)。

通过研究基线监视数据和图表,可以发现系统中有几个瓶颈:在 map 阶段,没有充分使用 CPU(大多数时候不到 40%),而且磁盘 I/O 相当频繁。

步骤 4:打破瓶颈

首先尝试提高 map 阶段的 CPU 利用率。前面对 Hadoop 参数的说明指出,要想提高 CPU 利用率,需要增加 mapred.tasktracker.map 和 reduce.tasks.maximum 参数的值。

在测试环境中,每个节点有两个支持并发多线程的 4 核处理器,所以有 16 个可用的位置,可以把这两个参数设置为 7。

为了完成这一修改,需要在 mapred-site.xml 中设置 mapred.tasktracker.map 和 reduce.tasks.maximum 参数,重新启动集群,再次启动 baseline_test.sh(因为在 mapred-site.xml 文件中进行配置,所以这里不需要修改脚本)。修改后的 mapred-site.xml 如下所示:

下面是调优后的测试结果:

执行时间:8599 秒

资源使用量汇总:

图 5. 调优后的 DataNode/TaskTracker 图表

步骤 5:新一轮调优,重复步骤 3 和 4

增加每个 TaskTracker 中 map/reduce 任务的最大数量之后,观察获取的数据和图表,可以看到在 map 阶段已经充分使用 CPU 了。

是与此同时,磁盘 I/O 频率仍然很高,所以需要新一轮调优-监视-分析过程。
需要重复这些步骤,直到系统中没有瓶颈,每种资源都充分使用为止。

注意,每次调优不一定会提高性能。如果出现性能下降,需要恢复以前的配置,尝试用其他调优措施打破瓶颈。在这次测试中,最终取得的优化结果如下:

执行时间:5670 秒

系统参数值:机架间带宽 = 1Gb

资源使用量汇总:

图 6. DataNode/TaskTracker 图表 - 第二轮调优

步骤 6:可伸缩性测试和改进

为了进一步检验调优结果,需要在使用优化后的配置的情况下增加集群规模和输入数据规模,从而测试配置的可伸缩性。具体地说,把集群规模增加到 30 个节点,把输入数据规模增加到 1.5TB,然后再次执行上面的测试过程。

由于篇幅有限,这里不详细描述调优过程。监视和分析方法与上面提到的完全相同,发现的主要瓶颈出现在网络中。当输入数据增加到 TB 量级时,机架间带宽变得不足。把机架间带宽增加到 4 Gb,10 节点集群优化后的所有其他参数保持不变,最终的执行时间是 5916 秒,这相当接近 10 节点集群优化后的结果(5670 秒)。

结束语

您现在了解了如何监视 Hadoop 集群、使用监视数据分析系统瓶颈和优化性能。希望这些知识能够帮助您充分使用 Hadoop 集群,更高效地完成作业。可以使用本文描述的方法进一步研究 Hadoop 的可配置参数,寻找参数配置与不同作业特征之间的关联。

另外,这种基于参数的调优比较 “静态”,因为一套参数配置只对于一类作业是最优的。为了获得更大的灵活性,您应该研究 Hadoop 的调度算法,寻找提高 Hadoop 性能的新方法。



专家视角看IT与架构
软件架构设计
面向服务体系架构和业务组件的思考
人人网移动开发架构
架构腐化之谜
谈平台即服务PaaS
更多...   

相关培训课程

云计算
Windows Azure 云计算应用开发

 
 

组织简介 | 联系我们 |   Copyright 2002 ®  UML软件工程组织 京ICP备10020922号

京公海网安备110108001071号