现在,我有一个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对计数器最大名称有限制,这个设置idmapreduce.job.counters.counter.name.max
用于配置这个限制。所以我将其增加到500
,web界面现在显示完整的计数器名称。但计数器的getName()
仍然返回截断的名称。
有人能解释一下吗?或者指出我的错误?非常感谢。
编辑1
我的Hadoop服务器配置由一台带有HDFS、YARN和map reduce本身的服务器组成。在map reduces过程中,会有一些计数器增量,在作业完成后,在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的内部。一些有趣的东西:
org.apache.hadoop.mapred.ClientServiceDelegate#getJobCounters
方法从带有TRUNCATED名称和FULL显示名称的纱线中返回一组计数器- 无法调试映射和reducer本身,但在日志记录的帮助下,
org.apache.hadoop.mapreduce.Counter#getName
方法似乎在reducer执行期间工作正常
Hadoop代码中没有在初始化后截断计数器名称的内容。所以,正如您已经指出的,mapreduce.job.counters.counter.name.max
控制计数器的名称最大长度(默认值为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);
我认为您需要执行以下步骤来解决您观察到的计数器名称问题:
- 调整
mapreduce.job.counters.counter.name.max
配置值 - 重新启动YARN/MapReduce服务
- 重新运行您的作业
我想,您仍然会看到旧作业的截断计数器名称。
getName()
似乎不赞成
或者,可以使用默认最大长度为255的getUri()
。
文档链接:
getUri()
我还没有亲自尝试过,但这似乎是解决这个问题的可能方法。