您的位置:

Metrics监控

一、Metrics监控教程

Metrics是一种轻量级的度量框架,用于测量代码中的各种指标。它可以度量JVM的Heap和非Heap内存使用情况、线程池参数、GC次数和持续时间、方法调用、请求当前线程等。通过将Metrics集成到应用程序中,我们可以度量应用程序的状态及其性能,并以便于理解和可视化的方式展示给用户。

Metrics提供了几种度量类型,如计数器,直方图,计时器和高斯分布度量等等。每个度量类型都有其自己的用途和实现。例如,计数器被用于度量数量,直方图被用于测量分布,计时器被用于测量持续时间。Metrics能够将数据发送到不同的目的地,如JMX,日志记录,Graphite和其他系统。

下面是一个使用Metrics的简单示例:

``` import com.codahale.metrics.Counter; import com.codahale.metrics.ConsoleReporter; import com.codahale.metrics.MetricRegistry; import java.util.concurrent.TimeUnit; public class TestMetrics { static final MetricRegistry metrics = new MetricRegistry(); private static final Counter successJobCounter = metrics.counter("success.jobs.count"); public static void main(String[] args) throws Exception{ ConsoleReporter reporter = ConsoleReporter.forRegistry(metrics) .convertRatesTo(TimeUnit.SECONDS) .convertDurationsTo(TimeUnit.MILLISECONDS) .build(); reporter.start(1, TimeUnit.SECONDS); while(true){ Thread.sleep(1000); successJobCounter.inc(); } } } ```

在上面的示例中,我们首先导入了Metrics的必要类。然后创建一个MetricRegistry实例和一个计数器实例successJobCounter。我们使用ConsoleReporter实例来定期将度量数据输出到控制台。最后在死循环中,我们逐个增加计数器successJobCounter的值。

二、Metrics监控JVM指标

Metrics提供了许多度量JVM指标的实现,例如内存使用情况、GC状态、线程池参数等。下面是一个例子,同时度量了对内存的使用情况和GC耗时:

``` import com.codahale.metrics.ConsoleReporter; import com.codahale.metrics.Gauge; import com.codahale.metrics.MetricRegistry; import com.codahale.metrics.jvm.BufferPoolMetricSet; import com.codahale.metrics.jvm.GarbageCollectorMetricSet; import com.codahale.metrics.jvm.MemoryUsageGaugeSet; import java.util.HashMap; import java.util.Map; import java.util.concurrent.TimeUnit; public class TestJVMMetrics { static final MetricRegistry metrics = new MetricRegistry(); public static void main(String[] args) throws Exception{ ConsoleReporter reporter = ConsoleReporter.forRegistry(metrics) .convertRatesTo(TimeUnit.SECONDS) .convertDurationsTo(TimeUnit.MILLISECONDS) .build(); reporter.start(1, TimeUnit.SECONDS); metrics.registerAll(new MemoryUsageGaugeSet()); metrics.registerAll(new GarbageCollectorMetricSet()); metrics.registerAll(new BufferPoolMetricSet()); while(true){ Thread.sleep(1000); } } } ```

在上面的示例中,我们导入了必要的类以测量JVM指标。程序通过构造ConsoleReporter实例并将MetricRegistry注册到其中来执行报告逻辑。我们使用registerAll()方法将几个度量对象注册到MetricRegistry中。最后,在无限循环中,程序每秒钟休眠1秒。

三、Metrics监控 缺陷

Metrics监控在使用时可能存在一些问题,下面我们将说明几个常见的问题:

1. 内存泄漏

Metrics度量周期性地生成新对象,并定期将这些对象传递给JMX Reporter以进行报告。这些对象在进行度量时会消耗一定内存。如果我们不小心地在每个周期结束时未释放对象,则可能会导致内存泄漏。

2. 延迟和负载问题

在非常繁忙的系统中,Metrics可能会增加一些延迟和负载。这是因为度量模板可能需要较长时间来完成,以及避免在高负载时进行阻止的线程安全问题。我们需要了解系统的负载级别,以便理解Metrics如何影响它。

3. 精度问题

Metrics提供了许多度量类型,包括计数器、直方图、计时器和高斯分布度量等。每个度量类型都有自己的用途和实现。但是,在某些情况下,我们需要注意精度问题。例如,当计数器向多个线程发出调用并同时增加值时,可能发生增加次数不精确的情况。

四、Metrics监控JVM指标 Splunk

可以将Metrics度量数据发送到不同的目的地,例如JMX、Graphite和Splunk等。Splunk是一种收集、索引和可视化数据的流行工具,可以将Metrics数据实时传输到Splunk平台以进行分析。

下面是一个将Metrics数据发送到Splunk的例子:

``` import com.codahale.metrics.ConsoleReporter; import com.codahale.metrics.MetricRegistry; import com.codahale.metrics.jvm.MemoryUsageGaugeSet; import com.codahale.metrics.jvm.ThreadStatesGaugeSet; import org.slf4j.LoggerFactory; import org.slf4j.Logger; import org.slf4j.MDC; import com.splunk.*; import java.util.Properties; import java.util.concurrent.TimeUnit; public class TestSplunkMetrics { static final MetricRegistry metrics = new MetricRegistry(); private static final Logger logger = LoggerFactory.getLogger(TestSplunkMetrics.class); public static void main(String[] args) throws Exception{ Properties props = new Properties(); props.load(TestSplunkMetrics.class.getResourceAsStream("/splunk.properties")); SplunkDestination destination = SplunkDestination.create(props); ConsoleReporter reporter = ConsoleReporter.forRegistry(metrics) .convertRatesTo(TimeUnit.SECONDS) .convertDurationsTo(TimeUnit.MILLISECONDS) .filter(new SplunkFilter()) .build(); reporter.start(1, TimeUnit.SECONDS); metrics.registerAll(new MemoryUsageGaugeSet()); metrics.registerAll(new ThreadStatesGaugeSet()); while(true){ MDC.put("app.name", "TestSplunkMetrics"); try{ Thread.sleep(1000); }catch(Exception e){ } logger.info("testing"); MDC.remove("app.name"); } } } ```

在上面的示例中,我们采用了Splunk的Java SDK,并且创建了一个SplunkDestination实例。console reporter仍然被用来周期性地打印Metrics监控值。在注册MemoryUsageGaugeSet、ThreadStatesGaugeSet和logger实例之后,在死循环中的日志记录器会写一条记录,将接收的消息传输到Splunk服务器。

五、Metrics监控接口流量

Metrics提供了一些库用于度量和处理HTTP的度量数据。下面是一个使用Metrics监控REST Api流量的例子:

``` import com.codahale.metrics.Counter; import com.codahale.metrics.ConsoleReporter; import com.codahale.metrics.Meter; import com.codahale.metrics.MetricRegistry; import com.codahale.metrics.Timer; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.servlet.ServletContextHandler; import org.eclipse.jetty.servlet.ServletHolder; import java.util.concurrent.TimeUnit; public class TestMetricsHTTP { static final MetricRegistry metrics = new MetricRegistry(); private static final Counter successCounter = metrics.counter("success.hits.count"); private static final Counter failureCounter = metrics.counter("failure.hits.count"); private static final Meter requestsMeter = metrics.meter("requests.count"); private static final Timer responseTimer = metrics.timer("response.time"); public static void main(String[] args) throws Exception{ ConsoleReporter reporter = ConsoleReporter.forRegistry(metrics) .convertRatesTo(TimeUnit.SECONDS) .convertDurationsTo(TimeUnit.MILLISECONDS) .build(); reporter.start(1, TimeUnit.SECONDS); ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS); context.setContextPath("/"); Server jettyServer = new Server(8080); jettyServer.setHandler(context); ServletHolder jerseyServlet = context.addServlet(org.glassfish.jersey.servlet.ServletContainer.class, "/*"); jerseyServlet.setInitOrder(0); jerseyServlet.setInitParameter("jersey.config.server.provider.packages", "com.test"); try { jettyServer.start(); jettyServer.join(); } catch (Exception e) { e.printStackTrace(); } finally { jettyServer.destroy(); } } } ```

在上面的示例中,我们从MetricsRegistry中实例化了Counter、Meter和Timer。Counter被用于计算成功或失败的请求数,Meter被用于计算每秒钟的请求次数,Timer被用于测量请求的响应时间。

在Jetty HTTP服务器中,Metrics数据就可以收集了。Jetty将HTTP请求按照REST参数路由到相应的REST端点,并在相应的REST端点中实现Metrics数据。例如,以下是一个简单的REST端点:

``` import com.codahale.metrics.annotation.Metered; import com.codahale.metrics.annotation.Timed; import javax.ws.rs.*; @Path("/") public class MetricRESTApi { @GET @Path("/test") @Metered @Timed public void test() { TestMetricsHTTP.requestsMeter.mark(); TestMetricsHTTP.responseTimer.time(); TestMetricsHTTP.successCounter.inc(); } } ```

在上面的示例中,我们使用了Metrics注释。Metered和Timed注释都被用来标记方法以收集Metrics监控信息。

六、Metric监控

Metric监控用于度量应用程序和操作系统的度量信息,例如CPU使用率、内存使用率、磁盘空间使用率等。Metric监控使用许多API和框架来帮助我们收集和处理监控信息,并将其可视化成有用的图表和报告。

下面是一个使用Micrometer库将Metrics数据发送到Graphite的例子:

``` import io.micrometer.core.instrument.Counter; import io.micrometer.core.instrument.MeterRegistry; import io.micrometer.core.instrument.Timer; import io.micrometer.graphite.GraphiteConfig; import io.micrometer.graphite.GraphiteMeterRegistry; import java.time.Duration; import java.util.concurrent.TimeUnit; public class TestMicrometerMetrics { static final MeterRegistry registry = new GraphiteMeterRegistry( GraphiteConfig.builder() .host("localhost") .port(2003) .prefix("test") .build(), Clock.SYSTEM ); private final Counter successCounter = registry.counter("success.hits.count"); private final Counter failureCounter = registry.counter("failure.hits.count"); private final Timer responseTimer = Timer.builder("response.time") .publishPercentileHistogram() .sla(Duration.ofMillis(500), Duration.ofMillis(700)) .register(registry); public static void main(String[] args) throws Exception{ while(true){ Thread.sleep(1000); TestMicrometerMetrics testMicrometerMetrics = new TestMicrometerMetrics(); testMicrometerMetrics.handleRequest(); } } public void handleRequest(){ try { Timer.Sample sample = Timer.start(registry); // 处理请求 sample.stop(responseTimer); successCounter.increment(); } catch (RuntimeException e) { failureCounter.increment(); } } } ```

在上面的示例中,我们使用Micrometer库将Metrics数据发送到Graphite。我们将Counter添加到MeterRegistry中,以便度量计数器类型的metric。我们还创建了一个Timer对象用于测量请求响应时间,并添加到MeterRegistry中。

七、Prometheus监控 Metrics值选取

Prometheus是一种开源监控系统,可用于收集和处理度量数据。Prometheus使用拉模型,而不是被动接收推模型。该系统可以处理大量的监控数据,并对未来由新的监控数据生成简单、可视化的数据。

下面是一个采用Prometheus监控API中的Meter样本选取的Metrics值的例子: