java - Hadoop Namenode 将 FSNamesystem 指标发送到具有损坏指标路径的 Graphite

标签 java hadoop metrics graphite graphite-carbon

我使用以下 hadoop-metrics2.properties 配置:

*.sink.graphite.class=org.apache.hadoop.metrics2.sink.GraphiteSink
*.period=10
namenode.sink.graphite.server_host=alex-monitoring
namenode.sink.graphite.server_port=2015
namenode.sink.graphite.metrics_prefix=prefix

Carbon 接收除 FSNamesystem 指标之外的所有指标,例如 CapacityUsed、CapacityUsed 等(完整描述 here)

我将所有 tcp 请求转储到 carbon,这就是我得到的:
<...>
prefix.dfs.FSNamesystem.Context=dfs.HAState=active.TotalSyncTimes=17 .Hostname=alex-hadoop1.TotalSyncCount 2 1550676511
prefix.dfs.FSNamesystem.Context=dfs.HAState=active.TotalSyncTimes=17 .Hostname=alex-hadoop1.NumInMaintenanceLiveDataNodes 0 1550676511
prefix.dfs.FSNamesystem.Context=dfs.HAState=active.TotalSyncTimes=17 .Hostname=alex-hadoop1.NumInMaintenanceDeadDataNodes 0 1550676511
<...>

这里的问题是路径中的空格:TotalSyncTimes=17 .Hostname=TotalSyncTimes 应该是一个不同的度量,但它以某种方式出现在度量路径中,在等号之后具有度量值,而且它根本不作为不同的度量发送/接收(因为 tcpdump 不会捕获具有此度量的数据包作为一个不同的度量)。

这是 GraphiteSink 或 Hadoop metric 2 的问题,我该如何解决?

最佳答案

Metric 记录由标签(如 hostname、context、sessionid 等)和指标(如 CapacityTotal、CapacityUsed 等)组成。

当指标记录被插入 GraphiteSink例如,它遍历其所有标签,将它们组合成一个前缀,然后使用标签的前缀导出每个指标(在该指标记录中)。

在 Hadoop 2.9.1 中,TotalSyncTimes引入了(字符串)度量,它反射(reflect)了在各种编辑日志上同步操作所花费的时间 - 每个 Activity 日志的时间(例如,“9 2”表示两个 Activity 日志,第一个为 9 毫秒,另一个为 2 毫秒)。

查看 HDFS 的代码(2.9.2 + 2.7.3),看起来每个字符串类型的度量都会自动转换为标签:

有问题的度量的定义:

@Metric({"TotalSyncTimes",
              "Total time spend in sync operation on various edit logs"})
  public String getTotalSyncTimes() {
    JournalSet journalSet = fsImage.editLog.getJournalSet();
    if (journalSet != null) {
      return journalSet.getSyncTimes();
    } else {
      return "";
    }
  }

(注意Metric注解是没有类型的,默认是DEFAULT类型)

然后,当它被迭代时,它将被转换为带有标签的字符串:
private MutableMetric newImpl(Type metricType) {
        Class<?> resType = this.method.getReturnType();
        switch(metricType) {
        case COUNTER:
            return this.newCounter(resType);
        case GAUGE:
            return this.newGauge(resType);
        case DEFAULT:
            return resType == String.class ? this.newTag(resType) : this.newGauge(resType);
        case TAG:
            return this.newTag(resType);
        default:
            Contracts.checkArg(metricType, false, "unsupported metric type");
            return null;
        }
    }

这意味着 TotalSyncTimes将嵌套在标签中:
...
name: "Hadoop:service=NameNode,name=FSNamesystem",
modelerType: "FSNamesystem",
tag.Context: "dfs",
tag.HAState: "active",
tag.TotalSyncTimes: "9 2 ",
...

因此,当指标记录为 TotalSyncTimes被推送到 GraphiteSink ,它将为每个指标附加一个无效的前缀(带空格),就像您展示的那样:
HAState=active.TotalSyncTimes=17 .Hostname=alex-hadoop
最重要的是,您可以采取以下几种解决方案:
  • 使用不同的方法(不是通过指标2)
  • 创建一个不同的 Graphite 接收器,它更能识别标签(我们所做的)并附加到 metrics2 而不是 GrahpiteSink

  • 顺便说一句,我仍然不确定这是否是 HDFS 代码中的错误,或者应该是设计上的错误。

    关于java - Hadoop Namenode 将 FSNamesystem 指标发送到具有损坏指标路径的 Graphite ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54791669/

    相关文章:

    php - 自定义跨域度量跟踪系统在 php 中的实现

    java - 具体进口和整体进口的优缺点

    java - Struts 2 - 获取应用程序的完整 URL

    hadoop - 我必须实现hadoop,这样它才能处理调用详细记录的数据?

    go - Prometheus 指标未使用 Prometheus Go 客户端显示

    java - 消费者连接到哪个分区?

    java - Apache 点燃查询

    java - 如何在 Vaadin 上使用 withConverter 方法防止 Binder 中出现 “null” 文本

    hadoop - Hadoop MapReduce:具有固定数量的输入文件?

    hadoop - Flume 不将日志写入 Hdfs