HiveHive Metrics体系
Posted dabokele
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HiveHive Metrics体系相关的知识,希望对你有一定的参考价值。
Hive常用的长服务主要有HiveServer2和MetaStore,这两者都可以配置一些监控数据。HiveServer2可以配置若干监控,有关HiveServer2的更多介绍可以查看文档Setting Up Hiveser2。
一、HiveServer2 UI
从Hive 2.0.0版本以后,提供了一个Hiveser2的UI界面,默认通过10002端口访问。在该页面上可以看到当前活跃的HiveServe2连接Sessions,以及日志,Metrics信息等。
http://host:10002/jmx 路径下可以获取到HiveServer2一些监控项,但主要是jvm相关的监控,通过参数配置可以增加其他监控项。Hive中可配置的Metrics相关信息可以参考Hive Metrics,大致列举如下,
参数 | 默认值 | 含义 |
---|---|---|
hive.metastore.metrics.enabled | false | 打开metastore的监控项 |
hive.server2.metrics.enabled | false | 打开hiveserver2的监控项 |
hive.service.metrics.class | org.apache.hadoop.hive.common.metrics.metrics2.CodahaleMetrics | hive监控体系实现类 |
hive.service.metrics.reporter | JSON_FILE, JMX | 监控信息的返回格式,可选JSON_FILE, CONSOLE, JMX多个选项用逗号分隔 |
hive.service.metrics.file.frequency | 5秒 | 监控项更新时间间隔 |
hive.service.metrics.file.location | /tmp/report.json | 当使用metrics2的默认类,并且返回JSON_FILE格式时,监控信息会输出到该文件中,文件内容会覆盖,时间间隔由参数控制 |
将参数hive.metastore.metrics.enabled
打开后,再次访问jmx路径会看到多了很多metrics:name=
开头的监控项,
hive的Metrics信息如下所示,
二、Hive源代码
如上图所示,可以看到有metrics:name=api_
以及metrics:name=active_calls_
开头的监控项明细信息,这些参数都在org.apache.hadoop.hive.common.metrics.metrics2.CodahaleMetrics
类中定义,正如上面提到的,这个类在Hive-2版本中是参数hive.service.metrics.class
的默认值。
1、MetricsFactory类
CodahaleMetrics
类是在org.apache.hadoop.hive.common.metrics.common.MetricsFactory
类中通过init
方法构造出来的,过程如下所示,通过参数来选择具体的实现类。
public synchronized static void init(HiveConf conf) throws Exception
if (metrics == null)
Class metricsClass = conf.getClassByName(
conf.getVar(HiveConf.ConfVars.HIVE_METRICS_CLASS));
Constructor constructor = metricsClass.getConstructor(HiveConf.class);
metrics = (Metrics) constructor.newInstance(conf);
JvmPauseMonitor, HiveMetastore, PerfLogger, Operation, SQLOperation, HiveServer2
等类通过调用MetricsFactory.getInstance
方法获取Metrics
对象。
1、Metrics收集
上面提到主要有5个类都会通过Metrics
对象收集监控数据,接下来逐个分析。
(1)org.apache.hadoop.hive.common.JvmPauseMonitor
从类注释看,该类是基于Hadoop中的JvmPauseMonitor
类实现的。当Hive启动JVM进程时会生成JvmPauserMonitor
对象来收集JVM相关的监控数据,比较常见的是HiveServer2
和HiveMetaStore
进程。使用方法如下,
JvmPauseMonitor pauseMonitor = new JvmPauseMonitor(conf);
pauseMonitor.start();
接下来看一下start
方法,在该方法中会生成一个守护线程,Monitor
是JvmPauserMonitor
内部类。
public void start()
Preconditions.checkState(monitorThread == null,
"JvmPauseMonitor thread is Already started");
monitorThread = new Daemon(new Monitor());
monitorThread.start();
在Monitor
类中,三次调用incrementMetricsCounter
方法调用Metrics.incrementCounter
方法来累加指定监控项的数值,
private void incrementMetricsCounter(String name, long count)
Metrics metrics = MetricsFactory.getInstance();
if (metrics != null)
try
metrics.incrementCounter(name, count);
catch (Exception e)
LOG.warn("Error Reporting JvmPauseMonitor to Metrics system", e);
这三次调用的监控项定义在MetricsConstant
中,
public static final String JVM_PAUSE_INFO = "jvm.pause.info-threshold";
public static final String JVM_PAUSE_WARN = "jvm.pause.warn-threshold";
public static final String JVM_EXTRA_SLEEP = "jvm.pause.extraSleepTime";
(2)HiveMetaStore
这个类中最主要的方法是startFunction
,如下所示,
private String startFunction(String function, String extraLogInfo)
incrementCounter(function);
logInfo((getThreadLocalIpAddress() == null ? "" : "source:" + getThreadLocalIpAddress() + " ") +
function + extraLogInfo);
if (MetricsFactory.getInstance() != null)
try
MetricsFactory.getInstance().startStoredScope(function);
catch (IOException e)
LOG.debug("Exception when starting metrics scope"
+ e.getClass().getName() + " " + e.getMessage(), e);
return function;
调用该方法的入口大致如下,每一次对元数据的操作,比如建表,建库,查表等都有对应的处理函数,同时会通过该方法更新一下Metrics信息。
所有通过CodahaleMetrics.startStoredScope
方法进行监控的指标,都会在方法名前加一个“api_”前缀。下面这段代码位于CodahaleMetrics
中。
public static final String API_PREFIX = "api_";
public void startStoredScope(String name) throws IOException
name = API_PREFIX + name;
if (threadLocalScopes.get().containsKey(name))
threadLocalScopes.get().get(name).open();
else
threadLocalScopes.get().put(name, new CodahaleMetricsScope(name, this));
(3)PerfLogger
在PerfLogger
中,主要在beginMetrics
方法中用到了Metrics
,而beginMetrics
方法的入口又是PerfLogBegin
。
public void PerfLogBegin(String callerName, String method)
long startTime = System.currentTimeMillis();
startTimes.put(method, new Long(startTime));
if (LOG.isDebugEnabled())
LOG.debug("<PERFLOG method=" + method + " from=" + callerName + ">");
beginMetrics(method);
PerfLogger
是一个辅助类,可以用于监控代码片段的执行效率,如上面的代码所示,当日志调整到DEBUG级别时,调用PerfLogger
相关方法将会打印方法的耗时信息等,在PerfLogEnd
方法中,将会输出一个方法完整的运行耗时等性能信息。当Hive需要排查性能问题时,可以使用本方法。
Hive中有多个类使用了PerfLogger
,比如org.apache.hadoop.hive.ql.Driver
,在compile
方法中的调用如下所示,
perfLogger.PerfLogBegin(CLASS_NAME, PerfLogger.PARSE);
ParseDriver pd = new ParseDriver();
ASTNode tree = pd.parse(command, ctx);
tree = ParseUtils.findRootNonNullToken(tree);
perfLogger.PerfLogEnd(CLASS_NAME, PerfLogger.PARSE);
在解析之前,调用PerfLogBegin
方法,传入类名,以及对应的parse
标识符,在这段逻辑结束时,调用PerfLogEnd
方法,传入相同参数,日志中将会显示这一段逻辑从开始到结束的执行时长等信息。
(4)HiveServer2
在HiveServer2中,直接操作Metrics
的地方只有两处,一处是在init
方法中,如下所示,当参数hive.server2.metrics.enabled
打开时,初始化MetricsFactory
生成对应的Metrics
类。
public synchronized void init(HiveConf hiveConf)
//Initialize metrics first, as some metrics are for initialization stuff.
try
if (hiveConf.getBoolVar(ConfVars.HIVE_SERVER2_METRICS_ENABLED))
MetricsFactory.init(hiveConf);
catch (Throwable t)
LOG.warn("Could not initiate the HiveServer2 Metrics system. Metrics may not be reported.", t);
cliService = new CLIService(this);
addService(cliService);
...
另一处是在stop
方法中,停止HiveServer2服务时,调用MetricsFactory.close()
方法关闭Metrics。
上面代码中,启动HiveServer2后,会生成CLIService
对象,后续连接该Server的提交的SQL任务,具体的Metrics信息都由下面的Operation
处理。
(4)Operation
及其子类
Operation
有两个直接子类MetadataOperation
和ExecuteStagementOperation
,子类继承关系如下图所示,
2、CodahaleMetrics
类
该类继承自org.apache.hadoop.hive.common.metrics.common.Metrics
类,
(1)incrementCounter(String name, long increment)
该方法在前面的代码中已经提到,根据监控项的名称name,找到对应监控项的值,然后增加该监控项的数值increment。
(2)decrementCounter(String name, long decrement)
与上面的方法功能相反,减少监控项的数值。
(2)startStoredScope
前面HiveMetaStore.startFunction
方法,连接该metastore执行不同操作时调用的方法,全部进入这个方法中,该方法的监控值加1,然后将数据存入StoredScope
对象中,这个对象中存储的数值可以由JMXReporter
或者JsonFileReporter
向外部暴露。
private String startFunction(String function, String extraLogInfo)
incrementCounter(function);
logInfo((getThreadLocalIpAddress() == null ? "" : "source:" + getThreadLocalIpAddress() + " ") +
function + extraLogInfo);
if (MetricsFactory.getInstance() != null)
try
MetricsFactory.getInstance().startStoredScope(function);
catch (IOException e)
LOG.debug("Exception when starting metrics scope"
+ e.getClass().getName() + " " + e.getMessage(), e);
return function;
(3)endStoredScope
从HiveMetaStore中开始过程与StartStoredScope
相反。
从当前线程中移除指定监控项。
public void endStoredScope(String name) throws IOException
name = API_PREFIX + name;
if (threadLocalScopes.get().containsKey(name))
threadLocalScopes.get().get(name).close();
threadLocalScopes.get().remove(name);
(5)addGauge
将监控项加入到监控存储对象metricRegistry
中,该对象是MetricRegistry
类型,后面有提到。
public void addGauge(String name, final MetricsVariable variable)
Gauge gauge = new Gauge()
@Override
public Object getValue()
return variable.getValue();
;
try
gaugesLock.lock();
gauges.put(name, gauge);
// Metrics throws an Exception if we don't do this when the key already exists
if (metricRegistry.getGauges().containsKey(name))
LOGGER.warn("A Gauge with name [" + name + "] already exists. "
+ " The old gauge will be overwritten, but this is not recommended");
metricRegistry.remove(name);
metricRegistry.register(name, gauge);
finally
gaugesLock.unlock();
(6)initReporting
初始化Reporter对象,由参数hive.service.metrics.reporter
控制,常用的是JMX, JSON_FILE。
3、Reporter
这里是向外部暴露Metrics信息的地方,常用的有以下两个实现,由参数hive.service.metrics.reporter
配置具体的输出方式。在上面的initReporting
来构造对应的Reporter。
(1)JMXReporter
略,位于metrics-core-3.1.0.jar
的com.codahale.metrics
路径下。构造好该对象,调用start
方法。
(2)JsonFileReporter
JsonFileReporter
是CodahaleMetrics
的内部类。start
方法定时从MetricRegistry
类中取出收集到的监控数据,输出到hive.service.metrics.file.location
路径下。
上面的Gauge
对象也通过metricRegistry.register(name, gauge)
方法注册进来。
以上是关于HiveHive Metrics体系的主要内容,如果未能解决你的问题,请参考以下文章
SpringBoot - 构建监控体系02_定义度量指标和 Actuator 端点
探秘 Dubbo 的度量统计基础设施 - Dubbo Metrics