目前碰到过三种原因导致 Time out after 300 secs。
1. 死循环
这是最常见的原因。显式的死循环很容易定位,隐式的死循环就比较麻烦了,比如正则表达式。曾经用一个网上抄来的邮箱正则表达式匹配百亿条数据,最终导致一个map阶段的attempt频繁超时重试,最后自己重写了一个简化版的表达式,问题解决。
2. 频繁GC
程序中生成了过多的全局对象会导致频繁GC。比如reduce阶段依赖一个不断增大的ArrayList变量,而ArrayList在增大过程中涉及到不断的copyOf,形成额外的时间和空间开销,最终导致任务超时。解决方法:任务提交时动态配置 -D mapreduce.reduce.memory.mb=5120 参数,增大reduce阶段内存。
3. 节点崩溃
这种比较少见,而且一般会出现在reduce阶段。因为map阶段的中间结果是保存在计算节点本地的,因此数据只有单一备份。如果reduce阶段时某个节点崩溃,会导致reduce计算节点无法获取该map节点的数据,造成Bad response ERROR for block。解决办法很简单,重新跑一次就好了。
补充:如果允许丢掉部分异常数据的话,可以设置 mapreduce.map.skip.maxrecords 和 mapreduce.reduce.skip.maxgroups 两个参数,分别表示map阶段可以跳过的最大错误记录数和reduce阶段可以跳过的最大错误组数。