作业调试
History Server开启
因为yarn集群重启之后,作业的历史运行日志和信息就被清理掉了,对于定位历史任务的错误信息很不友好,所以首先开启History Server用于保存所有作业的历史信息。
首先编辑yarn-site.xml文件,开启yarn的日志聚合功能。
代码语言:javascript复制cd $HADOOP_HOME/etc/hadoop
vim yarn-site.xml
添加的配置如下:
代码语言:javascript复制 <property>
<name>yarn.log-aggregation-enable</name>
<value>true</value>
</property>
<property>
<name>yarn.log-aggregation.retain-seconds</name>
<value>2592000</value>
</property>
<property>
<name>yarn.log.server.url</name>
<value>http://node01:19888</value>
</property>
<property>
<name>yarn.nodemanager.remote-app-log-dir</name>
<value>hdfs://node01:9000/yarn-logs/</value>
</property>
然后编辑mapred-site.xml文件,添加History-Server基本配置:
代码语言:javascript复制cd $HADOOP_HOME/etc/hadoop
vim mapred-site.xml
添加的配置如下:
代码语言:javascript复制 <property>
<name>mapreduce.jobhistory.address</name>
<value>node01:10020</value>
</property>
<property>
<name>mapreduce.jobhistory.webapp.address</name>
<value>node01:19888</value>
</property>
<property>
<name>mapreduce.jobhistory.intermediate-done-dir</name>
<value>/mr-history/log</value>
</property>
<property>
<name>mapreduce.jobhistory.done-dir</name>
<value>/mr-history/done</value>
</property>
因为集群搭建脚本中已经添加了前2个配置项,所以只需要添加后2个即可。
配置的具体含义如下:
然后重启集群,使配置生效:
代码语言:javascript复制stop-all.sh
start-all.sh
启动history-server:
代码语言:javascript复制mr-jobhistory-daemon.sh start historyserver
此时,可以在hdfs中看到HistoryServer的存储目录就被创建出来了。
于是,现在历史作业的运行信息就可以被保留下来了,但前提是在history-server在启动的情况下。
辅助脚本
作业清理&提交
MapReduce任务在集群中提交时,如果报错,则需要清理环境,删除jar包和中间编译的文件,并且在HDFS中删除结果输出目录。
如果频繁进行调试,那重复删除便会花费很多的时间,所以可以把这部分内容放置到脚本中去,节省时间。
代码语言:javascript复制#!/bin/bash
rm -rf SumDeptSalary.*
hadoop fs -rm -r /tmp/mr/data/sum_output
touch SumDeptSalary.java
除此之外,java程序的编译和提交也是重复工作,在测试过程中也可以加到脚本中。
代码语言:javascript复制#!/bin/bash
export HADOOP_CLASSPATH=${JAVA_HOME}/lib/tools.jar
hadoop com.sun.tools.javac.Main SumDeptSalary.java
jar cf SumDeptSalary.jar SumDeptSalary*.class
hadoop jar SumDeptSalary.jar SumDeptSalary /tmp/mr/data/dept_input/dept /tmp/mr/data/emp_input/emp /tmp/mr/data/sum_output
这些脚本是减少重复执行的时间,为了方便,所以不必写的那么通用,每次测试时重写一个就可以了。
日志查看
再有就是,MapReduce程序在集群中进行调试时,可以在程序中添加System.out来输出信息,当然更推荐使用log4j日志打印。
其中System.out输出的信息,会存放到 $HADOOP_HOME/logs/userlogs目录下对应application的中不同container输出的stderr和stdout文件中。
而log4j日志会存放到syslog中。
因为hadoop依赖中已经添加了log4j的日志包,所以在程序中直接使用即可。
代码语言:javascript复制// 定义成员变量logger,这里定义到了Mapper类MapClass中
public Logger logger = Logger.getLogger(MapClass.class.getName());
// 在函数中直接调用logger进行日志打印
logger.info("Log4j:进入SetUp方法");
其中log4j的配置文件存放在$HADOOP_HOME/etc/hadoop目录下,可以自定义修改。
程序输出日志后,然而寻找这些日志信息,首先需要在web监控界面查看任务的appication id和任务被提交到了哪些NodeManager中执行,然后分别进入到对应NodeManager节点中查看这些日志,而且因为每次执行的application id不同,导致找到并进入准确的目录花费的时间较长。所以可以编写一个日志查看脚本,从所有节点查询application id对应的日志并返回。
观察application id,末尾的序号是顺序递增的;在虚拟机测试环境中,不同于生产环境的严谨,只需要关注末尾的序号即可,比如0001、0002。所以在脚本中传入的KaTeX parse error: Expected group after '_' at position 28: …配application_*_̲{1}即可。
提供以下脚本,遍历所有从节点,并输出syslog日志。
代码语言:javascript复制#!/bin/bash
if [ $# -le 0 ]
then
echo 缺少参数
exit 1
fi
for n in `cat $HADOOP_HOME/etc/hadoop/slaves`
do
echo ===========查看节点 $n============
ssh $n "cat $HADOOP_HOME/logs/userlogs/application_*_${1}/container_*/syslog"
done
使用时,加上grep命令过滤,效果更佳。