整合 MapReduce 日志

Posted

技术标签:

【中文标题】整合 MapReduce 日志【英文标题】:Consolidate MapReduce logs 【发布时间】:2013-08-29 18:57:28 【问题描述】:

调试 Hadoop map-reduce 作业很痛苦。我可以打印到标准输出,但这些日志显示在运行 MR 作业的所有不同机器上。我可以去 jobtracker,找到我的工作,然后单击每个单独的 mapper 以访问其任务日志,但是当您有 20 多个 mapper/reducer 时,这非常麻烦。

我在想我可能需要编写一个脚本来遍历作业跟踪器,以找出每个映射器/减速器在哪台机器上运行,然后将日志 scp 回一个中心位置,在那里它们可能是 cat'一起编。在我浪费时间做这件事之前,是否有人知道一种更好的方法来为作业的映射器和减速器获取一个合并的标准输出日志?

【问题讨论】:

【参考方案1】:

我这样做的方式如下:

对于一般调试(即测试作业是否有效),我在本地机器上以独立模式运行 hadoop,并使用少量数据样本。这样,hadoop 就可以像任何其他 java 应用程序一样工作,并在控制台中显示映射器或减速器的标准输出。

对于特定的错误(即作业在我的本地机器上运行良好,但在生产中死机),我只需调整代码以作为作业的输出,我通常会在调试时发送到标准输出。这样,您可以检查作业的结果以获取调试见解。这不是很漂亮,但效果很好。

另一个选项是在 jobtracker 中检查节点的日志。他们有所有的标准输出和标准错误。但是,由于多种原因,我发现这比上述解决方案要复杂得多(一段时间后删除日志,要查找多个节点等)

【讨论】:

【参考方案2】:

所以我最终只是创建了一个 Python 脚本来执行此操作。这并不可怕。这是脚本,以防其他人想使用它。显然它需要更多的错误检查,而不是硬编码的网址等,但你明白了。注意,需要下载Beautiful Soup

#!/usr/bin/python
import sys
from bs4 import BeautifulSoup as BS
from urllib2 import urlopen
import re

TRACKER_BASE_URL = 'http://my.tracker.com:50030/'
trackerURLformat = TRACKER_BASE_URL + 'jobtasks.jsp?jobid=%s&type=%s&pagenum=1' # use map or reduce for the type

def findLogs(url):
    finalLog = ""

    print "Looking for Job: " + url
    html = urlopen(url).read()
    trackerSoup = BS(html)
    taskURLs = [h.get('href') for h in trackerSoup.find_all(href=re.compile('taskdetails'))]

    # Now that we know where all the tasks are, go find their logs
    logURLs = []
    for taskURL in taskURLs:
        taskHTML = urlopen(TRACKER_BASE_URL + taskURL).read()
        taskSoup = BS(taskHTML)
        allLogURL = taskSoup.find(href=re.compile('all=true')).get('href')
        logURLs.append(allLogURL)

    # Now fetch the stdout log from each
    for logURL in logURLs:
        logHTML = urlopen(logURL).read()
        logSoup = BS(logHTML)
        stdoutText = logSoup.body.pre.text.lstrip()
        finalLog += stdoutText

    return finalLog


def main(argv):
    with open(argv[1] + "-map-stdout.log", "w") as f:
        f.write(findLogs(trackerURLformat % (argv[1], "map")))
        print "Wrote mapers stdouts to " + f.name

    with open(argv[1] + "-reduce-stdout.log", "w") as f:
        f.write(findLogs(trackerURLformat % (argv[1], "reduce")))
        print "Wrote reducer stdouts to " + f.name

if __name__ == "__main__":
    main(sys.argv)

【讨论】:

我在这个脚本中做了一些改变(基本的 jobtracker url 是一个参数)并使它在 Python3 上工作。如果你想看,就在这里:github.com/OhadR/mapreduce-logs-consolidator【参考方案3】:

我的经验是,当您确切地知道是什么 map/reduce 尝试导致了您想要通过日志检查的问题时,您不需要点击 20 多个 map/reduce 输出链接。这就是为什么我在抛出异常或增加计数器时总是使用 Context.setStatus("Warn message here") 以引起怀疑。

更多关于 setStatus:http://hadoop.apache.org/docs/r1.1.1/api/org/apache/hadoop/mapreduce/TaskInputOutputContext.html#setStatus(java.lang.String)

https://www.inkling.com/read/hadoop-definitive-guide-tom-white-3rd/chapter-5/running-on-a-cluster(调试作业部分)

【讨论】:

以上是关于整合 MapReduce 日志的主要内容,如果未能解决你的问题,请参考以下文章

HBase整合MapReduce之建立HBase索引

mapreduce,整合数据字典表

如何记录hadoop mapreduce运行日志

spring boot 整合mapreduce运行的ClassNotFoundException

hadoop mapreduce的日志输出到哪里

Hadoop13:案例MapReduce任务日志查看