0.简介
Ambari作为一款针对大数据平台的运维管理工具,提供了集群的创建,管理,监控,升级等多项功能,目前在业界已经得到广泛使用。Ambari指标系统( Ambari Metrics System,以下简称AMS)主要负责监控平台各类服务及主机的运行情况,提供各类服务及主机的相关指标,从而达到判断集群健康情况的目的,其重要性不言而喻。
本文是在深入阅读AMS源代码的基础之上,力求能够从监控指标的采集、存储、聚合及指标获取4个层面详细阐述AMS的整个工作机制。
1.AMS指标采集
对于 AMS 本身来说,涉及的主要模块有 Metrics Monitor、Hadoop Sinks(此处统称,其中还包含kafka,storm,flume等服务的sinks,严格地来说应叫service sinks) 以及 Metrics Collector。AMS 也是一个 Master-Slave 结构的框架。Master 模块便是 Metrics Collector,Slave 则是 Metrics Monitor 和 Hadoop Sinks。Slave 模块负责收集信息,并发送给 Collector。当然 Metrics Monitor 和 Hadoop Sinks 也有不同的职责,前者主要负责收集机器本身相关的指标,例如 CPU、Mem、Disk 相关信息;后者则负责收集 Hadoop 相关 Service 模块的性能数据,例如该模块Namenode占用了多少 Mem,以及该模块的 CPU 占用率等。
1.1 指标收集
关于指标的采集,此处以Flume服务为例,剖析AMS是如何采集Flume运行的相应指标的。Ambari内置了FlumeTimelineMetricsSink这样的jar包,通过Ambari启动flume服务,ambari会在flume的启动脚本参数中加入以下两项:
-Dflume.monitoring.type=org.apache.hadoop.metrics2.sink.flume.FlumeTimelineMetricsSink
-Dflume.monitoring.node=<AMS_HOST>:6188
其中即为AMS collector的节点名字,而6188则是collector中的Timeline Server对外提供的默认端口,以此来向Timeline Server推送数据。
接下来再看一下FlumeTimelineMetricsSink jar包的结构,其中就包含一个FlumeTimelineMetricsSink类,继承自AbstractTimelineMetricsSink抽象类并实现MetricsSink接口,如上所示的所有服务的sink包基本都采用这样的结构。
FlumeTimelineMetricsSink类中内置一个TimelineMetricsCollector线程,在flume启动FlumeTimelineMetricsSink jar包时,其就通过其start方法中的线程调度器来轮询调度TimelineMetricsCollector线程,而在此线程中主段代码如下所示。
@Override
public void start() {
LOG.info("Starting Flume Metrics Sink");
TimelineMetricsCollector timelineMetricsCollector = new TimelineMetricsCollector();
if (scheduledExecutorService == null || scheduledExecutorService.isShutdown() || scheduledExecutorService.isTerminated()) {
scheduledExecutorService = Executors.newSingleThreadScheduledExecutor();
}
scheduledExecutorService.scheduleWithFixedDelay(timelineMetricsCollector, 0,
pollFrequency, TimeUnit.MILLISECONDS);
} }
从上面可看出Start方法中采取线程池的方法,以pollFrequency(可配置)的周期间隔,调度TimelineMetricsCollector线程,再细看一下TimelineMetricsCollector线程的详细说明,其主要代码如下所示。
class TimelineMetricsCollector implements Runnable {
@Override
public void run() {
try {
Map<String, Map<String, String>> metricsMap = JMXPollUtil.getAllMBeans();
long currentTimeMillis = System.currentTimeMillis();
for (String component : metricsMap.keySet()) {
Map<String, String> attributeMap = metricsMap.get(component);
LOG.debug("Attributes for component " + component);
processComponentAttributes(currentTimeMillis, component, attributeMap);
}
}
……………………………..
TimelineMetricsCollector线程轮循从服务的JMX端口中获取指标数据,形成Map对象,并通过processComponentAttributes方法进行逻辑转换后再发送。
1.2 指标推送
由上面源码可以看出,本质上,AMS的监控数据还是从各服务JMX端口中取得的,再通过processComponentAttributes方法逻辑上转换成AMS的内部的TimelineMetrics,通过emitMetrics方法post到Timeline Server(emitMetrics方法正是从AbstractTimelineMetricsSink类继承而来),其接口为:
http://:6188/ws/v1/timeline/metrics
如下是emitMetrics方法的部分片段,从中可以看出,emit方法最终还是将指标数据转化成json格式的数据,通过接口推送至TimelineServer。
protected void emitMetrics(TimelineMetrics metrics) throws IOException {
String connectUrl = getCollectorUri();
try {
String jsonData = mapper.writeValueAsString(metrics);
StringRequestEntity requestEntity = new StringRequestEntity(jsonData, "application/json", "UTF-8");
PostMethod postMethod = new PostMethod(connectUrl);
postMethod.setRequestEntity(requestEntity);
int statusCode = httpClient.executeMethod(postMethod);
……………………………
若是转换成curl命令的形式,则通过以下这样一条命令进行推送数据:
curl -i -X POST -H "Content-Type: application/json" -d "${json}" ${url}
其中json为转化成json的metrics数据,url为上面接口。
emitMetrics方法或curl命令发送的url最终会被Timeline server所截获,再通过TimelineMetricStore类以phonenix接口方式存储到Hbase数据库中,如下文TimelineWebServices类代码所示。
@Path("/metrics")
@POST
@Consumes({ MediaType.APPLICATION_JSON /* , MediaType.APPLICATION_XML */})
public TimelinePutResponse postMetrics(
@Context HttpServletRequest req,
@Context HttpServletResponse res,
TimelineMetrics metrics) {
init(res);
if (metrics == null) {
return new TimelinePutResponse();
}
try {
// TODO: Check ACLs for MetricEntity using the TimelineACLManager.
// TODO: Save owner of the MetricEntity.
return timelineMetricStore.putMetrics(metrics);
}
……………………………..
上文描述了Flume服务指标推送的大概过程,服务运行时主动推送指标, AMS接收推送指标。其它各类服务如hadoop,kafka,storm均以此种方式进行指标的推送,在此不再作详细讨论。
2.AMS指标存储
AMS采集到的服务指标通过http/https的方式推送到timeline server,timeline server内部嵌入了一个hbase,通过phoenix(nosql之上的sql查询)将指标数据存入到hbase中。
Hbase库中总共有7张表,其相应表名如下表所示。
表2-1 Metrics指标存储表
表名 | 描述 | 清理时间(默认) | 间隔(默认,单位:秒) |
---|---|---|---|
METRIC_RECORD | 用于记录每个机器上收集的每个Metrics属性 | 1天 | (1)主机metric:60;(2)hadoop metric 60 + 10 |
METRIC_RECORD_MINUTE | 聚合统计每个机器上的Metrics属性 | 1周 | 120 |
METRIC_RECORD_HOURLY | 聚合统计每个机器上的Metrics属性 | 30天 | 3600 |
METRIC_RECORD_DAILY | 聚合统计每个机器上的Metrics属性 | 1年 | 86400 |
METRIC_AGGREGATE | 聚合统计所有机器上的Metrics属性(集群) | 1周 | 30 |
METRIC_AGGREGATE_HOURLY | 聚合统计所有机器上的Metrics属性(集群) | 1年 | 3600 |
METRIC_AGGREGATE_DAILY | 聚合统计所有机器上的Metrics属性(集群) | 2年 | 86400 |
虽然库中一共有7张表,但是实际存储指标数据的只有METRIC_RECORD表,其它各表是在其基础之上做相应的统计及聚合而成的,下表是METRIC_RECORD表详细说明。
表2-2 METRIC_RECORD表字段说明
字段名称 | 类型 | 详细说明 |
---|---|---|
METRIC_NAME | VARCHAR | Metric名字 |
HOSTNAME | VARCHAR | 采集该metric的主机名字 |
SERVER_TIME | UNSIGNED_LONG | metric入进来的服务器时间 |
APP_ID | VARCHAR | 采集该Metric的服务,如果是mem_free这样的机器信息则为HOST(即由monitor发送过来的metric,其都为HOST),如果是dfs.*类似的metric则其为datanode,namenode,nodemanager等等 |
INSTANCE_ID | VARCHAR | 此次采集metric的示例id,一般为空 |
START_TIME | UNSIGNED_LONG | 开始采集metric的时间,通常比服务器早一分钟,这一分钟是monitor发送时间间隔或者hadoop sink配置的发送间隔时间 |
UNITS | CHAR | 一般为空,有的为LONG |
METRIC_SUM | DOUBLE | 该条metrics中,所有metric的总和 |
METRIC_COUNT | UNSIGNED_INT | 该条metrics中,所有metric的数量 |
METRIC_MAX | DOUBLE | 该条metrics中的最大值 |
METRIC_MIN | DOUBLE | 该条metrics中的最小值 |
METRICS | VARCHAR | (1)针对采集的hosts指标,即由monitor发送的指标值,采集的metric记录,有{时间戳1:值,时间戳2:值,。。。}这样的记录组成,其中树目标现在Metric_count上,对于monitor发送的metric,默认间隔为12条,每条间隔5秒钟,然后一分钟想timelineServer发送一次,存入表中。(2)针对采集的hadoop sink指标采集的metric记录,由有{时间戳1:值,时间戳2:值,。。。}这样的记录组成,每条间隔10秒钟,每隔70秒发送一次,采集7条,所以metric_count为7,一分钟向timelineserver发送一次,存入表中。 |
待续。。