Springboot 多数据源进行actuator监控
在Spring Boot应用中,如果你配置了多数据源,并且希望使用Actuator来进行监控,你需要确保每个数据源都被正确地配置和注册,以便Actuator能够发现和监控它们。Actuator提供了一系列端点(endpoints)来监控和管理Spring Boot应用,包括健康检查(health)、指标(metrics)、信息等。本文介绍Springboot多数据源使用Prometheus进行监控。
环境
springboot | 2.0.8.RELEASE |
---|---|
spring-boot-starter-parent | 2.0.8.RELEASE |
micrometer-registry-prometheus | 1.0.9 |
mybatis-plus-boot-starter | 3.1.0 |
dynamic-datasource-spring-boot-starter | 3.4.1 |
prometheus:v2.4.0 查看的1.8的文档
进行prometheus 查看此博客
1.配置多数据源的项目
pom
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.8.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.dalaoyang</groupId>
<artifactId>springcloud_prometheus_dynamic_datasource</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>springcloud_prometheus_dynamic_datasource</name>
<description>springcloud_prometheus_dynamic_datasource</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.1.0</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>dynamic-datasource-spring-boot-starter</artifactId>
<version>3.4.1</version>
</dependency>
<!-- Tag-应用监控埋点actuator-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!-- Tag-应用监控埋点actuator-->
<!-- Tag-将actuator监控的指标转为prometheus格式-->
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-registry-prometheus</artifactId>
<version>1.0.9</version>
</dependency>
<dependency>
<groupId>io.github.mweirauch</groupId>
<artifactId>micrometer-jvm-extras</artifactId>
<version>0.1.2</version>
</dependency>
<!-- Tag-将actuator监控的指标转为prometheus格式-->
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
<repositories>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
</repository>
</repositories>
</project>
application.yml
spring:
application:
name: springcloud_prometheu_dynamic_datasource
##数据库url
datasource:
dynamic:
primary: mysql
strict: true
datasource:
mysql:
url: jdbc:mysql://192.168.0.229:43306/test?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=CTT
driver-class-name: com.mysql.jdbc.Driver
username: root
password: Cobbler1234!
hikari:
minIdle: 10
maxPoolSize: 80
connectionTimeout: 10000
idleTimeout: 300000
maxLifetime: 1800000
connectionTestQuery: SELECT 1
validationTimeout: 5000
initializationFailTimeout: 1
scsdb_1:
username: SCS
password: 123456
url: jdbc:mysql://192.168.0.76:2200/bigdata?useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull&autoReconnect=true
driver-class-name: com.mysql.jdbc.Driver
hikari:
minIdle: 10
maxPoolSize: 80
connectionInitSql: set slave;start backup;
connectionTimeout: 10000
idleTimeout: 300000
maxLifetime: 1800000
connectionTestQuery: SELECT 1
validationTimeout: 5000
initializationFailTimeout: 1
scsop_1:
username: SCS
password: 123456
url: jdbc:mysql://192.168.0.76:2200/bigdata?useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull&autoReconnect=true
driver-class-name: com.mysql.jdbc.Driver
hikari:
minIdle: 10
maxPoolSize: 80
connectionInitSql: set slave;start backup;
connectionTimeout: 10000
idleTimeout: 300000
maxLifetime: 1800000
connectionTestQuery: SELECT 1
validationTimeout: 5000
initializationFailTimeout: 1
server:
port: 9905
management:
endpoints:
web:
exposure:
include: "*"
exclude: env,beans
endpoint:
metrics:
enabled: true
prometheus:
enabled: true
metrics:
tags:
application: ${spring.application.name}
export:
prometheus:
enabled: true
启动类
package com.liuhm;
import io.micrometer.core.instrument.MeterRegistry;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.actuate.autoconfigure.metrics.MeterRegistryCustomizer;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
@SpringBootApplication
public class SpringcloudPrometheuDynamicDatasourceApplication {
public static void main(String[] args) {
SpringApplication.run(SpringcloudPrometheuDynamicDatasourceApplication.class, args);
}
@Bean
MeterRegistryCustomizer<MeterRegistry> configurer(
@Value("${spring.application.name}") String applicationName) {
return (registry) -> registry.config().commonTags("application", applicationName);
}
}
2. 测试,检查数据源情况
访问 http://localhost:9904/actuator/prometheus
发现只有mysql数据源,没得其他数据源
3.查找问题
发现只绑定了一个数据源的配置信息
多数据源bean有全部的数据源信息
4.解决问题
重写这个类的方法,在自己项目路径下创建org.springframework.boot.actuate.autoconfigure.metrics.jdbc
包,在此包创建HikariDataSourceMetricsPostProcessor,
修改如下
/*
* Copyright 2012-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.boot.actuate.autoconfigure.metrics.jdbc;
import javax.sql.DataSource;
import com.baomidou.dynamic.datasource.DynamicRoutingDataSource;
import com.zaxxer.hikari.HikariDataSource;
import com.zaxxer.hikari.metrics.micrometer.MicrometerMetricsTrackerFactory;
import io.micrometer.core.instrument.MeterRegistry;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.boot.jdbc.DataSourceUnwrapper;
import org.springframework.context.ApplicationContext;
import org.springframework.core.Ordered;
import java.util.Map;
/**
* {@link BeanPostProcessor} that configures Hikari metrics. Such arrangement is necessary
* because a {@link HikariDataSource} instance cannot be modified once its configuration
* has completed.
*
* @author Stephane Nicoll
*/
class HikariDataSourceMetricsPostProcessor implements BeanPostProcessor, Ordered {
private static final Log logger = LogFactory
.getLog(HikariDataSourceMetricsPostProcessor.class);
private final ApplicationContext context;
private volatile MeterRegistry meterRegistry;
HikariDataSourceMetricsPostProcessor(ApplicationContext context) {
this.context = context;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) {
HikariDataSource hikariDataSource = determineHikariDataSource(bean);
if (hikariDataSource != null) {
Map<String, DataSource> dataSourceMap = ((DynamicRoutingDataSource) bean).getDataSources();
for(String key: dataSourceMap.keySet()){
HikariDataSource dataSource = determineHikariDataSource(dataSourceMap.get(key));
bindMetricsRegistryToHikariDataSource(getMeterRegistry(), dataSource );
}
}
return bean;
}
private HikariDataSource determineHikariDataSource(Object bean) {
if (bean instanceof DataSource) {
return DataSourceUnwrapper.unwrap((DataSource) bean, HikariDataSource.class);
}
return null;
}
private void bindMetricsRegistryToHikariDataSource(MeterRegistry registry,
HikariDataSource dataSource) {
if (!hasExisingMetrics(dataSource)) {
try {
dataSource.setMetricsTrackerFactory(
new MicrometerMetricsTrackerFactory(registry));
}
catch (Exception ex) {
logger.warn("Failed to bind Hikari metrics: " + ex.getMessage());
}
}
}
private boolean hasExisingMetrics(HikariDataSource dataSource) {
return dataSource.getMetricRegistry() != null
|| dataSource.getMetricsTrackerFactory() != null;
}
private MeterRegistry getMeterRegistry() {
if (this.meterRegistry == null) {
this.meterRegistry = this.context.getBean(MeterRegistry.class);
}
return this.meterRegistry;
}
@Override
public int getOrder() {
return Ordered.HIGHEST_PRECEDENCE;
}
}
多模块导入的情况下,该方法失效,就再将DataSourcePoolMetricsAutoConfiguration进行重写 ,在加个注解 @Primary
5. 测试
都有了