Gridmix



概述

GridMix 是 Hadoop 集群的基准测试。它提交了各种合成作业,模拟了从生产负载中挖掘的配置文件。此版本的工具将尝试对生产作业的资源配置文件进行建模,以识别瓶颈,指导开发。

要运行 GridMix,您需要一个 MapReduce 作业跟踪,描述给定集群的作业组合。此类跟踪通常由 Rumen 生成。GridMix 还需要合成作业将从中读取字节的输入数据。输入数据不必采用任何特定格式,因为合成作业当前是二进制读取器。如果您正在新集群上运行,则生成输入数据的可选步骤可能在运行之前执行。要模拟同一集群或其他集群上来自给定集群的生产作业的负载,请按照以下步骤操作

  1. 找到生产集群上的作业历史记录文件。此位置由集群的 mapreduce.jobhistory.done-dirmapreduce.jobhistory.intermediate-done-dir 配置属性指定。(MapReduce 历史记录服务器 将作业历史记录文件从 mapreduce.jobhistory.done-dir 移动到 mapreduce.jobhistory.intermediate-done-dir。)

  2. 运行 Rumen 以针对所有或选定作业构建 JSON 格式的作业跟踪。

  3. 在基准集群上使用作业跟踪和 GridMix。

GridMix 提交的作业的名称格式为“GRIDMIXnnnnnn”,其中“nnnnnn”是用前导零填充的序列号。

用法

Gridmix 作为 Hadoop 子命令提供。没有配置参数的基本命令行用法

$ hadoop gridmix [-generate <size>] [-users <users-list>] <iopath> <trace>

带配置参数的基本命令行用法

$ hadoop gridmix \
  -Dgridmix.client.submit.threads=10 -Dgridmix.output.directory=foo \
  [-generate <size>] [-users <users-list>] <iopath> <trace>

上述配置参数(如 -Dgridmix.client.submit.threads=10-Dgridmix.output.directory=foo)应在其他 GridMix 参数之前使用。

<iopath> 参数是 GridMix 的工作目录。请注意,它可以位于本地文件系统或 HDFS 上,但强烈建议它与原始作业组合相同,以便 GridMix 分别对本地文件系统和 HDFS 施加相同的负载。

-generate 选项用于生成合成作业的输入数据和分布式缓存文件。它接受标准单位大小后缀,例如 100g 将生成 100 * 230 字节作为输入数据。压缩格式输入数据的最小大小(默认 128MB)由 gridmix.min.file.size 定义。<iopath>/input 是生成输入数据的目标目录和/或将从中读取输入数据的目录。基于 HDFS 的分布式缓存文件在分布式缓存目录 <iopath>/distributedCache 下生成。如果一些所需的分布式缓存文件已存在于分布式缓存目录中,则仅在指定 -generate 选项时生成剩余的非现有分布式缓存文件。

-users 选项用于指向用户列表文件(请参阅 模拟用户和队列)。

<trace> 参数是 Rumen 生成的作业跟踪的路径。此跟踪可以压缩(必须使用集群支持的压缩编解码器之一读取)或未压缩。如果您想通过 GridMix 的标准输入流传递未压缩跟踪,请使用“-”作为此参数的值。

支持的配置参数在以下部分中进行了解释。

常规配置参数

参数 说明
gridmix.output.directory 将输出写入其中的目录。如果指定,iopath 将相对于此参数。提交用户必须具有对该目录的读/写访问权限。用户还应注意在运行期间可能出现的任何配额问题。默认值为“gridmix”。
gridmix.client.submit.threads 提交作业到集群的线程数。这也控制在给定时间将多少个拆分加载到内存中,具体取决于跟踪中的提交时间。拆分是预先生成的,以达到提交截止时间,因此特别密集的跟踪可能需要更多的提交线程。但是,将拆分存储在内存中相当昂贵,因此您应该谨慎提高此值。对于 SERIAL 作业提交策略(请参阅 作业提交策略),默认值为 1,对于其他策略,默认值为客户端计算机上的处理器数量加 1。
gridmix.submit.multiplier 加速或减慢作业提交的乘数。两个作业之间的时间间隔乘以这个因子。默认值为 1.0。这是一个将作业跟踪调整到集群的粗略机制。
gridmix.client.pending.queue.depth 等待拆分生成的作业描述队列的深度。从跟踪中读取的作业在由提交线程处理之前会占用此深度的队列。配置此项并不常见。默认值为 5。
gridmix.gen.blocksize 生成数据的块大小。默认值为 256 MiB。
gridmix.gen.bytes.per.file 每个文件写入的最大字节数。默认值为 1 GiB。
gridmix.min.file.size 输入文件最小大小。默认限制为 128 MiB。在使用相对较小的输入数据集测试 GridMix 时,如果您看到类似“未找到令人满意的文件”的错误消息,请调整此参数。
gridmix.max.total.scan 输入文件最大大小。默认限制为 100 TiB。
gridmix.task.jvm-options.enable 启用 Gridmix 使用从原始任务(即通过跟踪)获取的值来配置模拟任务的最大堆选项。

作业类型

GridMix 以作业跟踪作为输入,本质上是 JSON 编码作业描述的流。对于每个作业描述,提交客户端获取原始作业提交时间,并获取该作业中每个任务的读取和写入的字节和记录数。给定此数据,它将构建一个合成作业,其字节和记录模式与跟踪中记录的相同。它构建两种类型的作业

作业类型 说明
LOADJOB 模拟 Rumen 跟踪中提到的工作负载的合成作业。在当前版本中,我们支持 I/O。它在基准集群上复制 I/O 工作负载。它通过将每个映射和归约任务的详细 I/O 信息(例如读取和写入的字节和记录数)嵌入到每个作业的输入拆分中来实现此目的。映射任务通过中间映射输出数据进一步传递归约任务的 I/O 模式。
SLEEPJOB 合成作业,其中每个任务只“休眠”,持续时间与生产跟踪中观察到的相同。ResourceManager 的可扩展性通常受到每秒可以处理的心跳数的限制。(心跳是 NodeManager 发送的定期消息,用于更新其状态并从 ResourceManager 获取新任务。)由于基准集群通常是生产集群的一小部分,因此从属节点产生的心跳流量远低于生产集群的水平。一种可能的解决方案是在每个从属节点上运行多个 NodeManager。这会导致一个明显的问题,即合成作业产生的 I/O 工作负载会破坏从属节点。因此需要这样的工作。

以下配置参数会影响作业类型

参数 说明
gridmix.job.type 此键的值可以是 LOADJOB 或 SLEEPJOB 之一。默认值为 LOADJOB。
gridmix.key.fraction 对于 LOADJOB 类型的作业,用于键数据的记录部分。默认值为 0.1。
gridmix.sleep.maptask-only 对于 SLEEPJOB 类型的作业,是否忽略作业的归约任务。默认值为 false
gridmix.sleep.fake-locations 对于 SLEEPJOB 类型的作业,作业中映射任务的虚拟位置数。默认值为 0。
gridmix.sleep.max-map-time 对于 SLEEPJOB 类型的作业,作业中映射任务的最大运行时间(以毫秒为单位)。默认值为无限制。
gridmix.sleep.max-reduce-time 对于 SLEEPJOB 类型的作业,作业中归约任务的最大运行时间(以毫秒为单位)。默认值为无限制。

作业提交策略

GridMix 控制作业提交速率。此控制可以基于跟踪信息,也可以基于从 ResourceManager 收集的统计信息。根据用户定义的提交策略,GridMix 使用相应的算法来控制作业提交。目前有三种类型的策略

作业提交策略 说明
STRESS 持续提交作业,使集群保持在压力之下。在此模式下,我们通过监控集群的实时负载来控制作业提交速率,以便在集群上保持稳定的工作负载压力水平。根据我们收集的统计信息,我们定义集群是 *欠载* 还是 *过载*。当且仅当以下三个条件为真时,我们认为集群 *欠载*:
  1. 挂起的和正在运行的作业数低于阈值 TJ
  2. 挂起的和正在运行的映射数低于阈值 TM
  3. 挂起的和正在运行的归约数低于阈值 TR
阈值 TJ、TM 和 TR 分别与集群的大小和映射、归约槽容量成正比。如果集群 *过载*,我们将限制作业提交。在实际计算中,我们还会根据每个正在运行的任务的剩余工作对其进行加权 - 即,一个已完成 90% 的任务在计算中仅计为 0.1。最后,为了避免一个非常大的作业阻塞其他作业,我们限制每个作业可以贡献的挂起/等待任务数。
REPLAY 在此模式下,我们忠实地重放作业跟踪。此模式完全遵循实际作业跟踪中给出的时间间隔。
SERIAL 在此模式下,我们仅在较早提交的作业完成后才提交下一个作业。

以下配置参数会影响作业提交策略

参数 说明
gridmix.job-submission.policy 此键的值可以是以下三个值之一:STRESS、REPLAY 或 SERIAL。在大多数情况下,键的值将为 STRESS 或 REPLAY。默认值为 STRESS。
gridmix.throttle.jobs-to-tracker-ratio 在 STRESS 模式下,集群中正在运行的作业与 NodeManager 的最小比率,以使集群被视为 *过载*。这是前面提到的阈值 TJ。默认值为 1.0。
gridmix.throttle.maps.task-to-slot-ratio 在 STRESS 模式下,挂起和正在运行的映射任务(即未完成的映射任务)与集群映射槽数的最小比率,以便将集群视为 *过载* 。这是前面提到的 TM 阈值。正在运行的映射任务部分计数。例如,完成 40% 的映射任务计为 0.6 个映射任务。默认值为 2.0。
gridmix.throttle.reduces.task-to-slot-ratio 在 STRESS 模式下,挂起和正在运行的归约任务(即未完成的归约任务)与集群归约槽数的最小比率,以便将集群视为 *过载* 。这是前面提到的 TR 阈值。正在运行的归约任务部分计数。例如,完成 30% 的归约任务计为 0.7 个归约任务。默认值为 2.5。
gridmix.throttle.maps.max-slot-share-per-job 在 STRESS 模式下,在过载计算中,可以计入作业未完成映射任务的集群映射槽容量的最大份额。默认值为 0.1。
gridmix.throttle.reducess.max-slot-share-per-job 在 STRESS 模式下,在过载计算中,可以计入作业未完成归约任务的集群归约槽容量的最大份额。默认值为 0.1。

模拟用户和队列

典型的生产集群通常与不同的用户共享,并且集群容量通过作业队列在不同的部门之间分配。确保所有用户的作业公平性、遵守队列容量分配策略以及避免行为不当的作业接管集群,这给 Hadoop 软件增加了相当大的复杂性。为了能够充分测试和发现这些领域的错误,GridMix 必须模拟来自不同用户和/或提交到不同队列的作业的争用。

模拟多个队列很容易 - 我们只需使用与生产集群相同的队列配置设置基准集群,并将合成作业配置为使其提交到跟踪中记录的同一队列。但是,跟踪中显示的并非所有用户都在基准集群上拥有帐户。相反,我们设置了许多测试用户帐户,并以循环方式将跟踪中的每个唯一用户关联到测试用户。

以下配置参数会影响用户和队列的模拟

参数 说明
gridmix.job-submission.use-queue-in-trace 设置为 true 时,它使用与跟踪中提到的完全相同的队列集。默认值为 false
gridmix.job-submission.default-queue 指定将所有作业提交到的默认队列。如果未指定此参数,GridMix 将使用为集群上提交用户定义的默认队列。
gridmix.user.resolve.class 指定要使用的 UserResolver 实现。我们目前有三种实现
  1. org.apache.hadoop.mapred.gridmix.EchoUserResolver - 将作业提交为提交原始作业的用户。在这种情况下,作业跟踪中标识的所有生产集群用户还必须在基准集群上拥有帐户。
  2. org.apache.hadoop.mapred.gridmix.SubmitterUserResolver - 将所有作业作为当前 GridMix 用户提交。在这种情况下,我们只需将跟踪中的所有用户映射到当前 GridMix 用户并提交作业。
  3. org.apache.hadoop.mapred.gridmix.RoundRobinUserResolver - 以循环方式将跟踪用户映射到测试用户。在这种情况下,我们设置了多个测试用户帐户,并以循环方式将跟踪中的每个唯一用户关联到测试用户。
默认值为 org.apache.hadoop.mapred.gridmix.SubmitterUserResolver

如果参数 gridmix.user.resolve.class 设置为 org.apache.hadoop.mapred.gridmix.RoundRobinUserResolver,我们需要定义一个包含测试用户列表的用户列表文件。这是使用 -users 选项对 GridMix 进行指定的。

使用循环用户解析器时,必须使用 -users 选项指定用户列表文件。其他用户解析器会忽略此选项。

用户列表文件每行一个用户,每行的格式为

<username>

例如

user1
user2
user3

在上述示例中,我们定义了三个用户 user1user2user3。现在,我们将跟踪中的每个唯一用户与以循环方式定义的上述用户关联。例如,如果跟踪的用户是 tuser1tuser2tuser3tuser4tuser5,则映射如下

tuser1 -> user1
tuser2 -> user2
tuser3 -> user3
tuser4 -> user1
tuser5 -> user2

出于向后兼容性的原因,用户列表文件的每一行都可以包含用户名,后跟组名,格式为 username[,group]*. Gridmix 将忽略组名。

模拟分布式缓存加载

对于 LOADJOB 类型的作业,Gridmix 默认模拟分布式缓存加载。这是通过将所有模拟作业所需的分布式缓存文件作为单独的 MapReduce 作业的一部分进行预创建来完成的。

可以通过将属性 gridmix.distributed-cache-emulation.enable 配置为 false 来禁用 gridmix 模拟作业中的分布式缓存加载。但是,gridmix 生成分布式缓存数据是由 -generate 选项驱动的,并且与此配置属性无关。

如果

  • 输入跟踪来自标准输入流而不是文件,或者
  • 指定的 <iopath> 在本地文件系统上,则
  • 分布式缓存目录的任何上级目录,即 <iopath>/distributedCache(包括分布式缓存目录)对其他人没有执行权限。

模拟作业的配置

Gridmix3 在其提交的模拟作业中设置了一些配置属性,以便可以将它们映射回输入作业跟踪中的相应作业。这些配置参数包括

参数 说明
gridmix.job.original-job-id 与此模拟作业对应的原始集群作业的作业 ID。
gridmix.job.original-job-name 与此模拟作业对应的原始集群作业的作业名称。

模拟压缩/解压缩

MapReduce 支持数据压缩和解压缩。MapReduce 作业的输入可以压缩。类似地,Map 和 Reduce 任务的输出也可以压缩。GridMix 中的压缩/解压缩模拟非常重要,因为模拟压缩/解压缩会影响任务的 CPU 和内存使用情况。模拟压缩/解压缩的任务会影响在同一节点上运行的其他任务和守护进程。

如果 gridmix.compression-emulation.enable 设置为 true,则启用压缩模拟。默认情况下,为类型为 LOADJOB 的作业启用压缩模拟。启用压缩模拟后,GridMix 现在将生成具有恒定压缩比的压缩文本数据。因此,无论在实际作业中观察到的压缩比如何,模拟的 GridMix 作业现在都将使用可压缩文本数据(具有恒定压缩比)模拟压缩/解压缩。

典型的 MapReduce 作业在以下阶段处理数据压缩/解压缩

  • 作业输入数据解压缩:启用压缩模拟时,GridMix 会生成可压缩的输入数据。基于原始作业的配置,模拟的 GridMix 作业将使用解压缩器读取压缩的输入数据。目前,GridMix 使用 mapreduce.input.fileinputformat.inputdir 来确定原始作业是否使用了压缩的输入数据。如果原始作业的输入文件未压缩,则模拟作业将在不使用解压缩器的情况下读取压缩的输入文件。

  • 中间数据压缩和解压缩:如果原始作业启用了映射输出压缩,则 GridMix 也将为模拟作业启用映射输出压缩。相应地,还原器将使用解压缩器读取映射输出数据。

  • 作业输出数据压缩:如果原始作业的输出已压缩,则 GridMix 也将为模拟作业启用作业输出压缩。

以下配置参数会影响压缩模拟

参数 说明
gridmix.compression-emulation.enable 在模拟的 GridMix 作业中启用压缩仿真。默认值为 true。

在开启压缩仿真后,GridMix 将生成压缩的输入数据。因此,输入数据的总大小将小于预期大小。将 gridmix.min.file.size 设置为较小的值(大约为 gridmix.gen.bytes.per.file 的 10%),以使 GridMix 能够正确模拟压缩。

模拟高 RAM 作业

MapReduce 允许用户将作业定义为高 RAM 作业。高 RAM 作业中的任务可以在任务进程中占用更大比例的内存。模拟此行为很重要,原因如下。

  • 对调度程序的影响:调度高 RAM 作业中的任务会影响调度行为,因为它可能导致资源预留和利用。

  • 对节点的影响:由于高 RAM 任务占用更大的内存,NodeManager 会进行一些簿记,以便为这些任务分配额外的资源。因此,这成为内存仿真的先兆,其中具有高内存要求的任务需要被视为高 RAM 任务。

可以通过将

gridmix.highram-emulation.enable 设置为 false 来禁用高 RAM 功能仿真。

模拟资源使用情况

MapReduce 使用其任务计数器记录了 CPU、物理内存、虚拟内存、JVM 堆等资源的使用情况。GridMix 使用此信息来模拟模拟任务中的资源使用情况。模拟资源使用情况将帮助 GridMix 在测试集群上施加与实际集群中看到的类似负载。

MapReduce 任务在其整个生命周期内使用资源。GridMix 也尝试通过在模拟任务的整个生命周期内跨越资源使用仿真来模仿此行为。每个要模拟的资源都应与其关联一个仿真器。每个这样的仿真器都应实现 org.apache.hadoop.mapred.gridmix.emulators.resourceusage .ResourceUsageEmulatorPlugin 接口。GridMix 中的资源仿真器插件,可以在每次运行之前进行配置(插入或拔出)。GridMix 用户可以通过将逗号分隔的仿真器列表作为 gridmix.emulators.resource-usage.plugins 参数的值来配置多个仿真器插件

GridMix 附带的仿真器列表

  • 累积 CPU 使用率仿真器:GridMix 使用 Rumen 发布的累积 CPU 使用率值,并确保模拟任务的总累积 CPU 使用率接近 Rumen 发布的值。GridMix 可通过将 org.apache.hadoop.mapred.gridmix.emulators.resourceusage .CumulativeCpuUsageEmulatorPlugin 添加到为 gridmix.emulators.resource-usage.plugins 参数配置的仿真器插件列表中来配置为模拟累积 CPU 使用率。CPU 使用率仿真器设计为仅在任务的特定进度边界处进行仿真。此间隔可使用 gridmix.emulators.resource-usage.cpu.emulation-interval 进行配置。此参数的默认值为 0.1,即 10%

  • 总堆使用率仿真器:GridMix 使用 Rumen 发布的总堆使用率值,并确保模拟任务的总堆使用率接近 Rumen 发布的值。GridMix 可通过将 org.apache.hadoop.mapred.gridmix.emulators.resourceusage .TotalHeapUsageEmulatorPlugin 添加到为 gridmix.emulators.resource-usage.plugins 参数配置的仿真器插件列表中来配置为模拟总堆使用率。堆使用率仿真器设计为仅在任务的特定进度边界处进行仿真。此间隔可使用 gridmix.emulators.resource-usage.heap.emulation-interval 进行配置。此参数的默认值为 0.1,即 10% 进度间隔。

请注意,GridMix 仅对LOADJOB 类型的作业模拟资源使用率。

简化假设

GridMix 将分阶段开发,并纳入社区的反馈和补丁。目前,其目的是评估 MapReduce 和 HDFS 性能,而不是其上层的组件(即广泛的库和子项目空间)。鉴于这两个限制,作业负载的以下特征目前未在作业跟踪中捕获,并且无法在 GridMix 中准确重现

  • 文件系统属性 - 除了给定任务消耗和发出的字节/记录之外,不会尝试匹配块大小、命名空间层次结构或输入、中间或输出数据的任何属性。这意味着某些系统中最常用的部分(文本处理、流处理等)无法使用当前实现进行有意义的测试。

  • I/O 速率 - 消耗/发出的记录速率假定仅受读写器/写手的速度限制,并且在整个任务中保持恒定。

  • 内存概要 - 虽然保留了最大堆大小,但没有关于任务随时间推移的内存使用率的数据。

  • 倾斜 - 假设消耗和从给定任务发出的记录遵循观察到的平均值,即记录将比在野外看到的更规则。每个映射还会为每个归约生成一个按比例的百分比数据,因此具有不平衡输入的任务将被拉平。

  • 作业失败 - 假设用户代码是正确的。

  • 作业独立性 - 一个作业的输出或结果不会影响后续作业何时或是否运行。

附录

存在 GridMix 工具的较旧版本。跟踪 GridMix1GridMix2GridMix3 的原始实现的问题可在 Apache Hadoop MapReduce JIRA 中找到。可以通过搜索 Apache Hadoop MapReduce JIRA 来找到跟踪 GridMix 当前开发的其他问题。