以下的测试, 都是基于 Ubuntu 14.04.2 LTS + Java 8 + SpringBoot

Grafana 安装

sudo echo "deb https://packagecloud.io/grafana/stable/debian/ stretch main" > /etc/apt/sources.list.d/grafana.list
curl https://packagecloud.io/gpg.key | sudo apt-key add -
sudo apt-get update -y ; sudo apt-get install grafana

启动/停止

sudo service grafana-server start
sudo service grafana-server stop

登录:

http://127.0.0.1:3000

默认的用户名和密码都是 admin

登录后, 它会提示让你修改密码的.

InfluxDB 安装

cd ~/Downloads/
wget https://dl.influxdata.com/influxdb/releases/influxdb_1.5.4_amd64.deb
sudo dpkg -i influxdb_1.5.4_amd64.deb

启动/停止

service influxdb start
service influxdb stop

Java Metrics 的使用

pom.xml

        <dependency>
            <groupId>io.dropwizard.metrics</groupId>
            <artifactId>metrics-core</artifactId>
            <version>4.0.2</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/io.dropwizard.metrics/metrics-jvm -->
        <dependency>
            <groupId>io.dropwizard.metrics</groupId>
            <artifactId>metrics-jvm</artifactId>
            <version>4.0.2</version>
        </dependency>
        <dependency>
            <groupId>org.influxdb</groupId>
            <artifactId>influxdb-java</artifactId>
            <version>2.10</version>
        </dependency>
        <dependency>
            <groupId>com.github.davidb</groupId>
            <artifactId>metrics-influxdb</artifactId>
            <version>0.9.3</version>
        </dependency>

代码里使用

package com.company.metrics;

import com.codahale.metrics.*;
import com.codahale.metrics.jvm.*;
import com.company.util.MetricsUtil;
import metrics_influxdb.HttpInfluxdbProtocol;
import metrics_influxdb.InfluxdbReporter;
import metrics_influxdb.api.measurements.CategoriesMetricMeasurementTransformer;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.lang.management.ManagementFactory;
import java.lang.reflect.Field;
import java.util.concurrent.TimeUnit;

/**
 * @author emacsist
 */
@Component
public class AppMetrics {

    private static final Logger log = LoggerFactory.getLogger(AppMetrics.class);

    @Autowired
    private ReloadableProperties reloadableProperties;

    public static final MetricRegistry metrics = new MetricRegistry();


    @Value("${server.port}")
    private int port;

    @Value("${influxdb.host}")
    private String influxHost;

    @Value("${influxdb.user}")
    private String influxUser;

    @Value("${influxdb.passwd}")
    private String influxPasswd;

    @Value("${influxdb.db}")
    private String influxDB;

    @Value("${influxdb.port}")
    private int influxPort;

    @PostConstruct
    public void init() {
        initJVM();
        initProperties();

        if (StringUtils.isBlank(influxHost)) {
            startConsoleReporter();
        } else {
            influxDbReporter();
        }
    }

    private void initJVM() {
        metrics.register("jvm.gc", new GarbageCollectorMetricSet());
        metrics.register("jvm.thread-state", new CachedThreadStatesGaugeSet(10, TimeUnit.SECONDS));
        metrics.register("jvm.mem", new MemoryUsageGaugeSet());
        metrics.register("jvm.attr", new JvmAttributeGaugeSet());
        metrics.register("jvm.buffer-pool", new BufferPoolMetricSet(ManagementFactory.getPlatformMBeanServer()));
        metrics.register("jvm.fd.usage", new FileDescriptorRatioGauge());
    }


    private void influxDbReporter() {
        log.info("use influxdb as reporter {}:{}, {}, {}", influxHost, influxPort, influxUser, influxDB);
        final ScheduledReporter reporter = InfluxdbReporter.forRegistry(metrics)
                .protocol(new HttpInfluxdbProtocol("http", influxHost, influxPort, influxUser, influxPasswd, influxDB))
                .convertRatesTo(TimeUnit.SECONDS)
                .convertDurationsTo(TimeUnit.MILLISECONDS)
                .filter(MetricFilter.ALL)
                .skipIdleMetrics(false)
                //这里使用的是SpringBoot, 这是Java使用的监听的端口和本机IP地址, 来唯一表示该JVM进程, 你也可以使用其他的方式
                .tag("client", Integer.toString(port))
                .tag("server", MetricsUtil.getHost())
                .transformer(new CategoriesMetricMeasurementTransformer("module", "artifact"))
                .build();
        reporter.start(10, TimeUnit.SECONDS);
    }

    private void startConsoleReporter() {
        log.info("use console as reporter");
        ConsoleReporter reporter = ConsoleReporter.forRegistry(metrics)
                .convertRatesTo(TimeUnit.SECONDS)
                .convertDurationsTo(TimeUnit.MILLISECONDS)
                .build();
        reporter.start(10, TimeUnit.SECONDS);
    }

}

如果一切正常的话, 你就可以在 influxdb 中看到数据了.

> show measurements
name: measurements
name
----
PS-MarkSweep.count
PS-MarkSweep.time
PS-Scavenge.count
PS-Scavenge.time
blocked.count
count
daemon.count
deadlock.count
deadlocks
direct.capacity
direct.count
direct.used
heap.committed
heap.init
heap.max
heap.usage
heap.used
mapped.capacity
mapped.count
mapped.used
name
new.count
non-heap.committed
non-heap.init
non-heap.max
non-heap.usage
non-heap.used
pools.Code-Cache.committed
pools.Code-Cache.init
pools.Code-Cache.max
pools.Code-Cache.usage
pools.Code-Cache.used

这些就是 Java Metrics 收集的指标, 并保存在了 InfluxDB.

可视化监控数据

在 Grafana 中的数据源里, 配置好 InfluxDB 作为一个数据源.如下操作即可看到图表了:

img

其他的指标, 可以利用 Java Metrics 库来自定义.这里就不多说了. 主要思路即是: 在 Java Metrics 中收集好指标 -> 保存到 InfluxDB -> Grafana 查询出来, 保存好 Panel 即可.