禁用和替换默认 DataSourceHealthIndicator

Disable and Replace Default DataSourceHealthIndicator

我目前正在使用使用 Spring Boot Actuator "health" 端点实现的健康监控框架。 Actuator 基础设施支持创建自定义健康检查,还提供了一些内置的健康检查;其中之一是 DataSourceHealthIndicator.

DataSourceHealthIndicator is part of the org.springframework.boot.actuate.health 包,目前我们的健康框架正在使用它来检查数据源的健康状况。我需要使用我自己的 DataSourceHealthIndicator 稍微修改过的版本并禁用 "default."

我已经尝试了建议的解决方案 here and here,但没有成功。我可能做错了什么?

谢谢!


编辑:2016 年 8 月 18 日,3:38 东部时间下午

我已将我的 bean 重命名为 dbHealthIndicator 并将以下内容添加到我的配置 class:

@Bean
public HealthIndicator dbHealthIndicator() {
     return new dbHealthIndicator();
}

我现在遇到以下异常:

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'dataAccessMapperFactory' defined in class path resource [udtContext.xml]

java.lang.RuntimeException: java.sql.SQLException: Unable to start the Universal Connection Pool: oracle.ucp.UniversalConnectionPoolException


编辑:2016 年 8 月 19 日,9:22 美国东部时间上午

这可能有助于展示我正在尝试做的事情。目前,我的 /health 端点 return 看起来像这样:

dataSource: {
     status: "UP",
     database: "mySql",
     hello: "hello"
}

我想让它 return 更像这样,其中 "result" 旁边的整数是状态代码 return 由我的数据库中的存储过程编辑:

dataSource: {
     status: "UP",
     database: "mySql",
     hello: "hello",
     result: 0
}

这是 DataSourceHealthIndicator.java 中执行检查的方法:

private void doDataSourceHealthCheck(Health.Builder builder) throws Exception {
    String product = getProduct();
    builder.up().withDetail("database", product);
    String validationQuery = getValidationQuery(product);
    if (StringUtils.hasText(validationQuery)) {
        try {
            // Avoid calling getObject as it breaks MySQL on Java 7
            List<Object> results = this.jdbcTemplate.query(validationQuery,
                    new SingleColumnRowMapper());
            Object result = DataAccessUtils.requiredSingleResult(results);
            builder.withDetail("hello", result);
        }
        catch (Exception ex) {
            builder.down(ex);
        }
    }
}

我需要向此方法添加八行代码,在 builder.withDetail("hello", result); 下,以执行对存储过程的调用。我不想 "decompile" 默认值 class,而且我无法覆盖此方法,因为它是私有的。我在想我可以在我自己的 bean 中复制 DataSourceHealthIndicator.java 代码,添加我的代码,然后重新连接 Spring 以使用这个版本,但我不知道这是否可能。

通常我会查看 HealthIndicator 的配置。在本例中是 HealthIndicatorAutoConfiguration.DataSourcesHealthIndicatorConfiguration。正如第一个链接的建议所述。您需要将自定义 bean 命名为 dbHealthIndicator,以便 @ConditionalOnMissingBean(name = "dbHealthIndicator") 不允许注册默认值。

提供一些启动日志或不适合您的内容的详细信息将有助于人们进行故障排除。

这是我如何让它工作的示例:

@SpringBootApplication
public class WhosebugWebmvcSandboxApplication {
    @Bean
    public HealthIndicator dbHealthIndicator() {
        return new HealthIndicator() {

            @Override
            public Health health() {
                return Health.status(Status.UP).withDetail("hello", "hi").build();
            }
        };
    }

    public static void main(String[] args) {
        SpringApplication.run(WhosebugWebmvcSandboxApplication.class, args);
    }

    @RestController
    public class HelloController {
        @GetMapping("/hello")
        public String hello() {
            return "hello";
        }
    }
}

/health 端点随后返回:

{
    "status": "UP",
    "db": {
        "status": "UP",
        "hello": "hi"
    },
    "diskSpace": {
        "status": "UP",
        "total": 127927316480,
        "free": 17191956480,
        "threshold": 10485760
    }
}

没有提到的重要一点是,如果没有在数据源配置中设置 validationTimeoutconnectionTimeout 属性,我们将在 DataSourceHealthIndicatorhealth 上遇到无限循环检查系统变得完全none-functional,不管它的实现如何。

考虑到手头提供的案例,候选实施将如下所示。

@Component
@RequiredArgsConstructor
public class CustomHealth implements HealthIndicator {

    @Override
    public Health health() {
        ...
        return Health.status(healthIndicator.health().getStatus()).build();
    }

    private final DataSourceHealthIndicator healthIndicator;
}
        HikariConfig config = new HikariConfig();
        ...
        config.setInitializationFailTimeout(1000);
        config.setConnectionTimeout(1500);
        config.setValidationTimeout(1500);
        
        ...
        
    @Bean
    public DataSourceHealthIndicator dataSourceHealthIndicator(){
        return new DataSourceHealthIndicator(dataSource, "SELECT 1");
    }

另请注意,您可以在 属性 文件中简单地关闭执行器提供的默认 HealthIndicators。

YML

management:
  health:
    db:
      enabled: false
      
Properties

management.health.db.enabled: false