Hadoop 截断/不一致的计数器名称

现在,我有一个 Hadoop 作业,它创建的计数器有一个相当大的名称。

例如,下面这个: stats.counters.server-name.job.job-name.mapper.site.site-name.qualifier.qualifier-name.super-long-string-which-is-not-within-standard-limits。此计数器在 Web 界面和 getName()方法调用中被截断。我发现 Hadoop 对 counter max name 有限制,这个设置 id mapreduce.job.counters.counter.name.max用于配置这个限制。所以我增加到 500和 Web 界面现在显示完整的计数器名称。但是计数器的 getName()仍然返回截断的名称。

有没有人能解释一下,或者指出我的错误? 谢谢。

编辑1

我的 Hadoop 服务器配置由单个服务器组成,其中包含 HDFS、 YARN 和 map-reduce 本身。在 map-reduce 过程中,有一些计数器增量,在作业完成之后,在 ToolRunner中使用 org.apache.hadoop.mapreduce.Job#getCounters获取计数器。

编辑2

Hadoop 版本如下:

Hadoop 2.6.0-cdh5.8.0
Subversion http://github.com/cloudera/hadoop -r 042da8b868a212c843bcbf3594519dd26e816e79
Compiled by jenkins on 2016-07-12T22:55Z
Compiled with protoc 2.5.0
From source with checksum 2b6c319ecc19f118d6e1c823175717b5
This command was run using /usr/lib/hadoop/hadoop-common-2.6.0-cdh5.8.0.jar

我做了一些额外的调查,似乎 这个问题描述了一个类似于我的情况。但这是相当混乱的,因为我可以增加计数器的数量,但不计数器的名称的长度..。

编辑3

今天,我花了很多时间调试 Hadoop 的内部结构:

  1. 方法返回具有 截断名称和 满了显示名称的纱线中的一组计数器。
  2. 无法调试映射和减速器本身,但通过日志记录,似乎 org.apache.hadoop.mapreduce.Counter#getName方法可以在减速器执行期间正确工作。
3127 次浏览

getName()似乎不受欢迎

或者,可以使用默认最大长度为255的 getUri()

文档链接: getUri()

虽然没有亲自尝试过,但它似乎是解决这个问题的一个可能的方法。

Hadoop 代码中没有在初始化后截断计数器名称的内容。 因此,正如您已经指出的,mapreduce.job.counters.counter.name.max控制计数器的名称 max length (64个符号为 默认值)。

在调用 AbstractCounterGroup.addCounter/findCounter期间应用此限制。 相应的源代码是 跟随:

@Override
public synchronized T addCounter(String counterName, String displayName,
long value) {
String saveName = Limits.filterCounterName(counterName);
...

事实上:

public static String filterName(String name, int maxLen) {
return name.length() > maxLen ? name.substring(0, maxLen - 1) : name;
}


public static String filterCounterName(String name) {
return filterName(name, getCounterNameMax());
}

正如您所看到的,计数器的名称相对于 mapreduce.job.counters.max被保存为截断。 轮到它时,只有一个 Hadoop 代码中的单个位置执行对 Limits.init(Configuration conf)的调用(从 LocalContainerLauncher类调用) :

class YarnChild {


private static final Logger LOG = LoggerFactory.getLogger(YarnChild.class);


static volatile TaskAttemptID taskid = null;


public static void main(String[] args) throws Throwable {
Thread.setDefaultUncaughtExceptionHandler(new YarnUncaughtExceptionHandler());
LOG.debug("Child starting");


final JobConf job = new JobConf(MRJobConfig.JOB_CONF_FILE);
// Initing with our JobConf allows us to avoid loading confs twice
Limits.init(job);

我相信您需要执行以下步骤,以解决您所观察到的计数器名称问题:

  1. 调整 mapreduce.job.counters.counter.name.max配置值
  2. 重新启动 YARN/MapReduce 服务
  3. 重新运行你的工作

我认为,您仍然会看到旧作业的截断计数器名称。