Metrics即度量的意思,我们对系统做监控、统计等就需要用到Metrics。
metrics地址:https://github.com/dropwizard/metrics。
文档地址:https://metrics.dropwizard.io/4.0.0/。
本文使用的metrics-core和metrics-influxdb版本如下:
metrics-core=4.0.0
metrics-influxdb=0.8.0
jdk版本1.8
使用metrics统计controller的访问数
maven依赖
添加metrics-core
<dependency>
<groupId>io.dropwizard.metrics</groupId>
<artifactId>metrics-core</artifactId>
<version>${metrics.version}</version>
</dependency>
定义Metric配置
@Configuration
public class MetricsConfig {
@Bean
public MetricRegistry metricRegistry() {
MetricRegistry registry = new MetricRegistry();
// 输出到控制台
ConsoleReporter reporter = ConsoleReporter.forRegistry(registry)
.convertRatesTo(TimeUnit.SECONDS)
.convertRatesTo(TimeUnit.SECONDS)
.build();
reporter.start(5,TimeUnit.SECONDS);
return registry;
}
@Bean
public Meter userControllerMeter(MetricRegistry registry) {
Meter meter = registry.meter("userControllerMeter");
return meter;
}
}
测试Controller:
@Controller
@RequestMapping(value = "/user")
public class UserController {
@Autowired
@Qualifier("userControllerMeter")
private Meter userControllerMeter;
/**
* 存储用户信息的List。
*/
private Map<String,String> userInfos = new HashMap<String,String>(5) {{
put("test","测试用户");
put("root","root用户");
put("admin","管理员");
}};
@RequestMapping(value = "/get")
public ModelAndView test(ModelAndView mv, @RequestParam String userid) {
userControllerMeter.mark();
String user = getUserById(userid);
mv.setViewName("/test");
mv.addObject("user",user);
return mv;
}
/**
* 模拟一个获取用户信息的操作。
* @param userid
* @return
*/
private String getUserById(String userid) {
if (StringUtils.isEmpty(userid)) {
return null;
}
// 这里模拟是一个耗时的操作,比如从其他系统获取用户信息。
long sleepTime = (long) (Math.random()*10*1000+1);
try {
Thread.sleep(sleepTime);
} catch (InterruptedException e) {
e.printStackTrace();
}
return userInfos.get(userid);
}
}
在浏览器中输入http://localhost:8081/user/get?userid=test,并访问多次。
控制台输出:
可以看到,Meters统计了总的访问次数,当前的频率(每秒多少次),1分钟内、5分钟内、15分钟内的频率。
使用Metrics统计某个方法的调用时间
这里我们统计调用UserController中
1.MetricsConfig增加:
@Bean
public Timer getUserTime(MetricRegistry registry) {
Timer timer = registry.timer("getUserTimeTimer");
return timer;
}
2.UserController修改
@Autowired
@Qualifier("getUserTime")
private Timer getUserTime;
// 统计调用getUserById耗费的时间
Timer.Context context = getUserTime.time();
String user = getUserById(userid);
context.stop();
在浏览器中输入http://localhost:8081/user/get?userid=test,并访问多次。
控制台输出:
可以看到,Timer统计了总的调用次数,当前的调用次数(每秒多少次)、1分钟、5分钟、15分钟,最小耗时,最大耗时,平均耗时,75%的调用耗时,95%,98%,99%的调用耗时。
Metrics数据的可视化
这里以Influxdb和Grafana来构建一个实时的监控界面。
处理流程如下:采集数据(Metrics)——>存储数据(InfluxDB)——>展示数据(Grafana)。
安装InfluxDB
wget http://dl.influxdata.com/influxdb/releases/influxdb-0.12.2-1.x86_64.rpm
yum localinstall influxdb-0.12.2-1.x86_64.rpm
安装后启动服务:
service influxdb start
启动成功后,浏览器输入ip:8083访问。
到设置中,
可以看到http端口为8086,用户名和密码为空,这里我们设置用户名和密码都为root。
安装Grafana
参考:https://blog.csdn.net/syshzbtt/article/details/71574204。
wget https://s3-us-west-2.amazonaws.com/grafana-releases/release/grafana-4.2.0-1.x86_64.rpm
sudo yum localinstall grafana-4.2.0-1.x86_64.rpm
安装后启动服务:
service grafana-server start
浏览器输入IP:3000访问,用户名和密码为admin。
将数据收集到Influxdb
前面我们将数据直接输出到控制台,我们制定的Metrics Reporter为ConsoleReporter
,这里写入Influxdb,需要引入一个依赖:
<dependency>
<groupId>com.github.davidb</groupId>
<artifactId>metrics-influxdb</artifactId>
<version>${metrics.influxdb.version}</version>
</dependency>
MetricsConfig修改:
我们将收集到的统计数据发送到InfluxDB
ScheduledReporter reporter = InfluxdbReporter.forRegistry(registry)
// influxdb的ip,port,用户名,密码,数据库
.protocol(InfluxdbProtocols.http("192.168.200.99",8086,"root","root","my-influxdb"))
.convertRatesTo(TimeUnit.SECONDS)
.convertDurationsTo(TimeUnit.MILLISECONDS)
.filter(MetricFilter.ALL)
.skipIdleMetrics(false)
.build();
reporter.start(5,TimeUnit.SECONDS);
我们到InfluxDB的管理页面创建一个数据库
点击Create Database
,在Query中填入CREATE DATABASE "my-influxdb"
然后回车,数据库就创建好了。
在Grafana的管理页面新建一个DataSource
,
在Home
页面,New一个dashboard
点Graph
点Panel Title
点Edit
点General
可以修改标题
在Metrics
中,点SQL可以可视化编辑SQL。A From
后面的default
是默认数据源(在上面新建数据源时可以指定为默认数据源,或自己指定为你上面创建数据源名称),userControllerMeter
是表名。在上面MetricsConfig中指定的名称,我们也可以在Influxdb中根据它来查询。如图:
第二行field(value)
即我们要监控的指标,这里对应的就是count
字段,ALIAY BY
即是字段的别名,图表中显示用。点空白处,如果图表还是没数据,将日期显示范围扩大。
这样,就可以看到如下的图表
遇到的问题:
Caused by: java.lang.UnsupportedClassVersionError: com/justin/metrics/config/MetricsConfig : Unsupported major.minor version 52.0 (unable to load class com.justin.metrics.config.MetricsConfig)。
我的metrics-demo模块用的jdk7,引入的metrics-influxdb版本是0.8.2(mvn仓库最低就是这个版本),但0.8.2使用的jdk8编译的,所以有这个问题。
但是,将metrics-demo模块的jdk改成1.8后,还是有这个问题。最后更改整个project的版本为1.8解决。
这里只是作为一个演示,这是偏运维的东西,但作为开发人员还是有必要了解一下。
参考:https://www.jianshu.com/p/e4f70ddbc287、https://www.jianshu.com/p/fadcf4d92b0e。
源代码:https://gitee.com/qincd/my-test-projects/下metrics-demo
模块。