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

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

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

【问题讨论】:

    标签: logging hadoop mapreduce


    【解决方案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)
      

      【讨论】:

      【解决方案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(调试作业部分)

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-08-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-06-27
        相关资源
        最近更新 更多