1、Spring Boot 工程集成 Micrometer
我们一般说 Spring Boot 集成 Micrometer 指的是 Spring 2.x 版本,因为在该版本 spring-boot-actuator
使用了 Micrometer 来实现监控,而在 Spring Boot 1.5x 中是可以通过micrometer-spring-legacy
来使用 micrometer。显然在 2.x 版本中有更高的集成度,使用起来也非常方便了。首先添加依赖如下:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!--micrometer桥接prometheus-->
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-registry-prometheus</artifactId>
<!-- <version>1.1.4</version>-->
</dependency>
这里引入了 io.micrometer
的 micrometer-registry-prometheus
依赖以及 spring-boot-starter-actuator
依赖,因为该包对 Prometheus 进行了封装,可以很方便的集成到 Spring Boot 工程中。
其次在 application.properties
中配置如下:
spring.application.name=metricsLocalTestApp
server.port=9000
management.server.port=9001
management.endpoints.web.exposure.include=*
management.endpoint.metrics.enabled=true
management.endpoint.prometheus.enabled=true
management.metrics.export.prometheus.enabled=true
management.metrics.tags.application=${spring.application.name}
- 这里
management.endpoints.web.exposure.include=*
配置为开启 Actuator 服务,因为Spring Boot Actuator 会自动配置一个 URL 为/actuator/Prometheus
的 HTTP 服务来供 Prometheus 抓取数据,不过默认该服务是关闭的,该配置将打开所有的 Actuator 服务。 management.metrics.tags.application
配置会将该工程应用名称添加到计量器注册表的 tag 中去,方便后边 Prometheus 根据应用名称来区分不同的服务。
然后在工程启动主类中添加 Bean 如下来监控 JVM 性能指标信息:
@SpringBootApplication
public class GatewayDatumApplication {
public static void main(String[] args) {
SpringApplication.run(GatewayDatumApplication.class, args);
}
@Bean
MeterRegistryCustomizer<MeterRegistry> configurer(
@Value("${spring.application.name}") String applicationName) {
return (registry) -> registry.config().commonTags("application", applicationName);
}
}
最后,我们再启动服务,然后在浏览器访问 http://127.0.0.1:9001/actuator/prometheus
,就可以看到服务的一系列不同类型 metrics 信息,例如 http_server_requests_seconds summary
、jvm_memory_used_bytes gauge
、jvm_gc_memory_promoted_bytes_total counter
等等。
到此,Spring Boot 工程集成 Micrometer 就已经完成,接下里就要与 Prometheus 进行集成了。
2、集成 Prometheus
修改 Prometheus 的配置文件 prometheus.yml
,添加上边启动的服务地址来执行监控。这里使用的Prometheus版本是2.26.0
。
Mac下安装 Prometheus + grafana,可参照:Mac部署Prometheus + Grafana监控
vim /usr/local/etc/prometheus.yml
global:
scrape_interval: 15s
scrape_configs:
- job_name: "prometheus"
static_configs:
- targets: ["localhost:9090"]
- job_name: "metricsLocalTest"
metrics_path: "/actuator/prometheus"
static_configs:
- targets: ["localhost:9001"]
static_configs
为静态配置方式,也可以采用 file_sd_configs
方式动态服务发现的方式,如:
scrape_configs:
- job_name: "metricsLocalTest"
metrics_path: "/actuator/prometheus"
file_sd_configs:
- files: ['/usr/local/*[自己电脑上的路径]*/*.json']
metricsLocalApplication.json
文件如下:
$ vim /usr/local/*[自己电脑上的路径]*/*.json
[
{
"targets": [
"localhost:9001"
],
// 可填可不填
"labels": {
"instance": "metricsLocalTest-instance",
"service": "metricsLocalTest-service"
}
}
]
这里 localhost:9001
就是上边本地启动的服务地址,也就是 Prometheus 要监控的服务地址。同时可以添加一些与应用相关的标签,方便后期执行 PromSQL 查询语句区分。最后重启 Prometheus 服务
,查看 Prometheus UI 界面确认 Target 是否添加成功。
Status=》Targets
我们也可以在 Graph 页面执行一个简单的查询,也是获取 metricsLocalTest
服务的 JVM 性能指标值的。
3、使用 Grafana Dashboard 展示监控项
Prometheus 现在已经可以正常监控到应用 JVM 信息了,我们可以配置 Grafana Dashboard 来优雅直观的展示出来这些监控值了。
Mac下安装 Prometheus + grafana,可参照:Mac部署Prometheus + Grafana监控
配置数据源
首先启动 Grafana,在浏览器中访问 http://localhost:3000
即可,首次登录需要使用默认账号密码 admin/admin
进行登录。 登录完毕,我们就可以配置Prometheus数据源,数据源配置如下图所示:
点击Add data source
,搜索 Prometheus 数据源,然后填入 Prometheus 的访问地址。
在此,Prometheus 数据源配置就完成了。然后点击Save & Test
,提示正常连接,就可以使用了。
配置面板
数据源配置完成后,就可以选择面板,来渲染数据。JVM 数据监控,有现成的面板,我们直接使用即可,模板编号为4701
导入对应的模板
导入完毕后,就可以看到 JVM监控指标测试
各种类型指标监控图形化以后的页面。
Application
可以选择我们的应用。
4、自定义监控指标并展示到 Grafana
上边是 spring-boot-actuator
集成了 Micrometer 来提供的默认监控项,覆盖 JVM 各个层间的监控,配合 Grafana Dashboard 模板基本可以满足我们日常对 Java 应用的监控。当然,它也支持自定义监控指标,实现各个方面的监控,例如统计访问某一个 API 接口的请求数,统计实时在线人数、统计实时接口响应时间等功能,而这些都可以通过使用Micrometer
来实现。接下来,来演示下如何自定义监控指标并展示到 Grafana 上。
监控所有API请求次数
监控请求次数可以使用 Counter 计数器来处理,这里是为测试,直接在Controller类中进行累计,项目中,可以使用一个AOP切面,通过切面注入可以做到统计所有请求记录。
Java 代码如下所示:
@RestController
@RequestMapping("/gateway/metrics")
public class GrafanaTestController {
@Autowired
private MeterRegistry meterRegistry;
private Counter counter;
@PostConstruct
public void init() {
Tags tags = Tags.of("common", "test");
// 公共标签
meterRegistry.config().commonTags(tags);
counter = Counter.builder("metrics.request.common").register(meterRegistry);
}
/**
* 订单请求测试
*/
@GetMapping("/order/{appId}")
public RestResponse<String> orderTest(@PathVariable("appId") String appId) {
counter.increment();
return RestResponse.ok(appId);
}
/**
* 产品请求测试
*/
@GetMapping("/product/{appId}")
public RestResponse<String> productTest(@PathVariable("appId") String appId) {
counter.increment();
return RestResponse.ok(appId);
}
}
然后分别访问接口/order/{appId}
8次,访问接口/product/{appId}
6次,然后再去 Promtheus 中去查询数据,可以看到结果为14
标签为我们打的公共标签。
在这里简单解释一下带条件的查询语句,如:metrics_request_common_total{application="metricsLocalTestApp", common="test", instance="localhost:9001"}
,与上面使用的metrics_request_common_total
等价,其中:
-
metrics_request_common_total
为上边代码中设置的 Counter 名称。 -
application
为初始化 registry 时设置的通用标签,标注应用名称,这样做好处就是可以根据应用名称区分不同的应用。 -
instance
为<local_dir>/metricsLocalApplication.json
中配置的 instance 实例名称,用来区分应用实例。 -
common
为上边代码中设置的 Counter 标签名称,可以用来区分不同的方法,这样就不用为每一个方法设置一个 Counter 了。
接下来,我们在 Grafana Dashboard 上添加一个新的 Panel 并添加 Query 查询,最后图形化展示出来。
1、首先添加一个 Panel,并命名为 自定义监控指标
,选择想要展示的图形,如:这些图、柱状图等。
2、然后增加一个新的 Query 查询,查询语句为上边的 PromSQL 语句,不过这里为了更好的扩展性,我们可以将 application
及 instance
两个参数赋值为变量,而这些变量可以直接从 Prometheus 上传递过来,最终的查询语句为 metrics_request_common_total
,最后修改 Title 为 访问量测试
,保存一下,返回首页就可以看到刚添加的 Dashboard 了。
分类监控API请求次数
上边针对订单请求和产品请求,统计了接口调用的总次数,但是有时候,我们需要统计每个接口的调用次数,这个该如何实现呢?监控请求次数可以继续使用 Counter 计数器,不同的是,我们每个请求中的 Counter 的名称和标签不一样,和接口信息有关。
/**
* 订单请求测试
*/
@GetMapping("/order/{appId}")
public RestResponse<String> orderTest(@PathVariable("appId") String appId) {
counter.increment();
Counter.builder("metrics.request.count").tags("appMark", appId, "apiCode", "order").register(meterRegistry).increment();
return RestResponse.ok(appId);
}
/**
* 产品请求测试
*/
@GetMapping("/product/{appId}")
public RestResponse<String> productTest(@PathVariable("appId") String appId) {
counter.increment();
Counter.builder("metrics.request.count").tags("appMark", appId, "apiCode", "product").register(meterRegistry).increment();
return RestResponse.ok(appId);
}
同样的,我们分别访问接口/order/{appId}
8次,访问接口/product/{appId}
6次,然后再去 Promtheus 中去查询数据,可以看到结果分别为8和6。
Grafana 的图形界面展示操作,和监控所有API请求次数
一致。