• Hadoop全链路监控解决方案


    前言

    我在最近的几篇文章中都或多或少的提到了一个很重要的词-"监控".为什么要提到这个词呢,因为如果你和我一样是一名大数据工程师,你手下管理着批量的集群机器,并且同时这个集群的规模还会不定时的扩大,机器一旦变多,发生问题的频率和类型就会变多,所以这是,你靠人肉去分析某台机器上的日志,OK,1台机器,2台机器,尚且可以解决办法,但是100台,1000台呢,当然如果工程师还这么做的话,我想他会抓狂的.所以如何做到智能化发现问题,定位问题,就显得很关键了,最理想的结果是,你拥有你的集群机器中每天跑的job的各种指标数据,然后你动动鼠标,通过展示出来的图形界面,就迅速的发现了问题.这也是正是我最近在做的一件事情,效果还算不错.下面是我近1个月来,对于我们部门的Hadoop集群做的一些监控方面的事情,谈不上高大上的结构,我们是如何以最简单的方式达到最大化的效果,希望能给大家带来帮助.


    监控两大主题

    监控的大方向是想好了,但是我们要监控哪些指标,有必要提一下,要想做好监控,首先你要了解Hadoop这一整套的系统逻辑,大致了解即可,那么我们是怎么做的呢.分为2大方向,宏观层面和微观层面.宏观角度的理解就是Node级别,拓扑结构级别,DataNode,NameNode,JournalNode,ResourceManager,NodeManager,主要就是这5大组件,通过分析这些节点上的监控数据,一般你能够定位到慢节点,可能某台机器的网络出问题了,或者说某台机器执行的时间总是大于正常机器等等这样类似的问题.刚刚说的是一个监控方向,还有1个是微观层面,就是细粒度化的监控,基于user用户级别,基于单个job,单个task级别的监控,像这类监控指标就是另一大方向,这类的监控指标在实际的使用场景中特别重要,一旦你的集群资源是开放给外面的用户使用,用户本身不了解你的这套机制原理,很容易会乱申请资源,造成严重拖垮集群整体运作效率的事情,所以这类监控的指标就是为了防止这样的事情发生.


    宏观层面监控

    OK,两大主题监控方向确定,下面谈谈具体的实践方案,想必这也是大家所关心的.首先要先想能不能通过最简单的方式直接拿到一些数据,比如RPC接口去取,这样的方式的确是有的,我们用了YarnClient的获取nodeReport方法,做了这么一个获取工具,下面是核心代码:

    YarnClient client;
    		client = YarnClient.createYarnClient();
    		client.init(new Configuration());
    		client.start();
    
    List<NodeReport> nodesReport = client.getNodeReports();
    ...
    这样就得到nodeManager中的许多数据,包括正在运行的container数量,使用的内存大小,核数多少等等信息,同理DataNode的数据也可以以类似的方式获取,这里就不给出代码了.在分节点的统计代码中,还有一项指标也可以帮助我们发现节点异常问题,我们对各个IP对namenode的rpc请求量做了统计,对namenode的请求其实就是对HDFS的请求最了统计.当然,这个统计肯定要自己去分析才能得到.分析日志中的哪条记录信息呢,如果你没有阅读过NameNode和FSNameSystem这2个类的代码,你可能会不知道,hadoop在设计的时候,考虑的比较好,对于Client的每次请求,都做了请求记录的输出,名字叫做audit日志:

    /**
       * Default AuditLogger implementation; used when no access logger is
       * defined in the config file. It can also be explicitly listed in the
       * config file.
       */
      private static class DefaultAuditLogger extends HdfsAuditLogger {
       ....
    
        @Override
        public void logAuditEvent(boolean succeeded, String userName,
            InetAddress addr, String cmd, String src, String dst,
            FileStatus status, UserGroupInformation ugi,
            DelegationTokenSecretManager dtSecretManager) {
          
          if (auditLog.isInfoEnabled()) {
            final StringBuilder sb = auditBuffer.get();
            sb.setLength(0);
            sb.append("allowed=").append(succeeded).append("	");
            sb.append("ugi=").append(userName).append("	");
            sb.append("ip=").append(addr).append("	");
            sb.append("cmd=").append(cmd).append("	");
            sb.append("src=").append(src).append("	");
            sb.append("dst=").append(dst).append("	");
            if (null == status) {
              sb.append("perm=null");
            } else {
              sb.append("perm=");
              sb.append(status.getOwner()).append(":");
              sb.append(status.getGroup()).append(":");
              sb.append(status.getPermission());
            }
            if (logTokenTrackingId) {
              sb.append("	").append("trackingId=");
              String trackingId = null;
              if (ugi != null && dtSecretManager != null
                  && ugi.getAuthenticationMethod() == AuthenticationMethod.TOKEN) {
                for (TokenIdentifier tid: ugi.getTokenIdentifiers()) {
                  if (tid instanceof DelegationTokenIdentifier) {
                    DelegationTokenIdentifier dtid =
                        (DelegationTokenIdentifier)tid;
                    trackingId = dtSecretManager.getTokenTrackingId(dtid);
                    break;
                  }
                }
              }
              sb.append(trackingId);
            }
            sb.append("	").append("proto=");
            sb.append(NamenodeWebHdfsMethods.isWebHdfsInvocation() ? "webhdfs" : "rpc");
            logAuditMessage(sb.toString());
          }
        }
    
    里面的信息非常全,有用户者,操作命令,操作的源文件,目标文件,请求ip,其实单纯这几个信息,就可以帮助我们分析出很多有价值的信息了,当然我们先用他来分析基于IP的请求统计.这些记录如果你不做特殊的处理,他是零散的分布于nameode日志中的,所以你要把他从茫茫的记录中筛选出来,单独放到一个文件中,这个hadoop也是可以做到的,配置log4j的配置文件,增加下面的配置信息.

    #
    # hdfs audit logging
    #
    hdfs.audit.logger=INFO,RFAAUDIT
    hdfs.audit.log.maxfilesize=256MB
    hdfs.audit.log.maxbackupindex=100
    log4j.logger.org.apache.hadoop.hdfs.server.namenode.FSNamesystem.audit=${hdfs.audit.logger}
    log4j.additivity.org.apache.hadoop.hdfs.server.namenode.FSNamesystem.audit=false
    log4j.appender.RFAAUDIT=org.apache.log4j.RollingFileAppender
    log4j.appender.RFAAUDIT.File=${hadoop.log.dir}/hdfs-audit.log
    log4j.appender.RFAAUDIT.layout=org.apache.log4j.PatternLayout
    log4j.appender.RFAAUDIT.layout.ConversionPattern=%d{ISO8601} %p %c{2}: %m%n
    log4j.appender.RFAAUDIT.MaxFileSize=${hdfs.audit.log.maxfilesize}
    log4j.appender.RFAAUDIT.MaxBackupIndex=${hdfs.audit.log.maxbackupindex}
    这样就会单独的输出名字为hdfs-audit.log的文件数据了.分析的方式就是写个程序做文本解析,进行count计数即可.我们对这个文件还做了但分钟级别qps请求量的趋势统计,分用户级别的请求量分析,大家也可以这么去做.

    总的来说,离线的统计方式基本可以采用这样的方式去做,配lo4j单独打出某个类的日志,单类文件进行解析.


    微观层面监控

    微观层面的监控就要比宏观层面的监控要复杂许多,首先同样你要了解一定的理论只是,在Hadoop中,一个job是以怎么样的方式执行,如何转化,到最后的任务结束.当然在这里不可能一次性讲清楚.现在只要知道,这么几个名次,Application,Job,Task,Container,我们所说的细粒度监控指的也就是对这些变量进行监控.当然这些指标的量级是很大的,Application应用数和Job数也是可以1天过万的,这些job生成的task小的十几,多则上千个task,总的也可能达到1天上百万个task在跑.对于微观层面的监控,采用分析日志的方式,就不见得会很适合,应该并没有一个完整的地方会把每次task的启动信息大全,所以我们需要借助一下Hadoop自身对job的监控,就是JobHistory,这个类中就保存了历史执行过的job的执行信息,1个job里面会有所有执行过得task信息 ,task里又会包含有很多task attempt的信息。我们可以模拟JobHistory解析jHistoryFile格式的job信息文件进行信息的分析。当然你可以自己找到job的Path,做纯文本的解读。这方面的内容可以阅读我的这篇文章,JobHistory的job信息获取与分析。在task级别还有1个可以做的方面是增加counter,增加更多的自定义counte,counter的指标可以更加多元化,比如task Gc次数,full Gc总次数,reduce过程最后产生的文件数等等,这些指标都能细粒度的反映出这个task的执行好坏,如何加自定义的counter,大家也可以阅读我的这篇文章自定义Counter添加。还有1个微观层次的监控是基于用户的监控,将获取到的task,job这些按照用户进行聚合,排序,进行二次分析,就能找到问题用户,使用资源的大户。


    基于Hadoop源码的改造监控升级

    这个监控改造是一个升级,补充了前者监控中的不足,因为前面2个都是属于离线分析,事后分析,我们当然需要实时的结果数据,当然我们不会再做一个类似的实时数据收集展示平台,我们直接改JobHistory界面,ResourceManager后台显示界面,展示更多的页面信息在界面上,老实说,目前的Hadoop版本中的一些Ganglia监控指标和JobHistoty的显示信息,实在有限,分为2种情况,Ganglia上是我们想要的监控目标上面没有,所以我们只能自己再加,JobHistory上则是指标太多,导致上面只显示了公共常见的一些信息,很多都是要点击到页面里才能看,因此我们做的改进是把里面的信息放出来。当然这些改造都是我们内部自己对Hadoop的源码进行改造的。


    不足之处

    1.这个不足之处是目前对于我们部门来说可以补充去做的地方,冷热数据的分析,这个也可以通过hdfs-audit日志文件,根据访问命中次数,然后动态调整相应的副本数,提高读写效率。

    2.集群所有文件的结构分析,比如所有文件的大小范围分布情况,是不是小文件在集群中占了很大的比例,这个需要对fsimage文件做分析,这个我们之前也做过,但是没有做出工具,只是临时的解析了一下。

    3.Container数据的获得,Container的数据在JobHistory上没有的,上面只有1个containerId。container的信息也很有用,上面有许多的优先级,还有附加的信息都可以了解到机器资源的使用情况等等。


    工具分享链接

    下面是我近端时间做分析工具的一些部分核心代码,供大家学习使用:

    JobHistory文件手动分析工具:https://github.com/linyiqun/yarn-jobhistory-crawler/tree/master/jobHiveSqlAnalyse

    NodeManager定时状态信息获取工具:https://github.com/linyiqun/yarn-jobhistory-crawler/tree/master/NMTool

    JobHistory文件程序分析工具:https://github.com/linyiqun/yarn-jobhistory-crawler

    HDFS RPC分用户,IP请求分析工具:https://github.com/linyiqun/yarn-auditlog-parser

  • 相关阅读:
    Title
    Title
    Title
    Title
    Python生成随机验证码
    Time模块和datetime模块
    For循环的实质
    Python函数
    集合set
    字符串内置方法的使用
  • 原文地址:https://www.cnblogs.com/bianqi/p/12183844.html
Copyright © 2020-2023  润新知