[spring-projects/spring-boot]当排除 DataSourceAutoConfiguration 并且用户定义的数据源可用时,数据源指标不可用

2024-04-23 845 views
5

Spring Boot 2.0.2.RELEASE

我有一个 Spring Boot 应用程序,配置为使用 JPA 并将指标发送到 New Relic。 New Relic 正在从应用程序接收指标,但不接收 Hikari 连接指标。

我使用 Postman 向应用程序“metrics”端点发送请求。返回的指标列表不包含任何“hikari.connections”指标。该列表也不包含任何“jdbc.connections”指标。该列表确实包含其他指标,例如“jvm”。和“rabbitmq”,所以端点正在工作,并且千分尺似乎提供了一些指标(就像我上面所说的,New Relic 证实了这一点)。

启动应用程序时,控制台指示 HikariCP-2.7.9.jar 位于类路径上。应用程序能够成功连接到数据库并且存储库正常工作。

OnClassCondition 上的跟踪在控制台中显示了这一行:

8:39:04.807 TRACE 326836 --- [  restartedMain] o.s.b.a.condition.OnClassCondition       : Condition OnClassCondition on org.springframework.boot.actuate.autoconfigure.metrics.jdbc.DataSourcePoolMetricsAutoConfiguration$HikariDataSourceMetricsConfiguration matched due to @ConditionalOnClass found required class 'com.zaxxer.hikari.HikariDataSource'; @ConditionalOnMissingClass did not find unwanted class

控制台还提示一个HikariDataSource启动成功

2018-05-29 18:39:08.801  INFO 326836 --- [ost-startStop-1] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Starting...
2018-05-29 18:39:08.967  INFO 326836 --- [ost-startStop-1] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Start completed.

日志中剩余的 Hikari 输出如下:

2018-05-29 18:39:14.320  INFO 326836 --- [  restartedMain] o.s.j.e.a.AnnotationMBeanExporter        : Bean with name 'hikariConfig' has been autodetected for JMX exposure
2018-05-29 18:39:14.320  INFO 326836 --- [  restartedMain] o.s.j.e.a.AnnotationMBeanExporter        : Bean with name 'dataSource' has been autodetected for JMX exposure
2018-05-29 18:39:14.327  INFO 326836 --- [  restartedMain] o.s.j.e.a.AnnotationMBeanExporter        : Bean with name 'rabbitConnectionFactory' has been autodetected for JMX exposure
2018-05-29 18:39:14.327  INFO 326836 --- [  restartedMain] o.s.aop.framework.CglibAopProxy          : Method [void com.zaxxer.hikari.HikariConfig.seal()] is package-visible across different ClassLoaders and cannot get proxied via CGLIB: Declare this method as public or protected if you need to support invocations through the proxy.
2018-05-29 18:39:14.715  INFO 326836 --- [  restartedMain] o.s.j.e.a.AnnotationMBeanExporter        : Located MBean 'dataSource': registering with JMX server as MBean [com.zaxxer.hikari:name=dataSource,type=HikariDataSource]

让我知道您还需要哪些其他信息。谢谢。

回答

0

@nosan 感谢您的建议,但该问题的修复已在 Hikari 2.7.9 中进行,因此无需尝试 3.0。

@730alchemy 我无法根据您提供的信息重现问题。使用 Spring Boot 2.0.2 的最小应用程序列出了以下指标:

http :8080/actuator/metrics
HTTP/1.1 200
Content-Type: application/vnd.spring-boot.actuator.v2+json;charset=UTF-8
Date: Wed, 30 May 2018 08:38:26 GMT
Transfer-Encoding: chunked

{
    "names": [
        "jvm.memory.max",
        "http.server.requests",
        "process.files.max",
        "jvm.gc.memory.promoted",
        "tomcat.cache.hit",
        "system.load.average.1m",
        "tomcat.cache.access",
        "jvm.memory.used",
        "jvm.gc.max.data.size",
        "jdbc.connections.max",
        "jdbc.connections.min",
        "jvm.gc.pause",
        "jvm.memory.committed",
        "system.cpu.count",
        "logback.events",
        "tomcat.global.sent",
        "jvm.buffer.memory.used",
        "tomcat.sessions.created",
        "jvm.threads.daemon",
        "system.cpu.usage",
        "jvm.gc.memory.allocated",
        "tomcat.global.request.max",
        "hikaricp.connections.idle",
        "hikaricp.connections.pending",
        "tomcat.global.request",
        "tomcat.sessions.expired",
        "hikaricp.connections",
        "jvm.threads.live",
        "jvm.threads.peak",
        "tomcat.global.received",
        "hikaricp.connections.active",
        "hikaricp.connections.creation",
        "process.uptime",
        "tomcat.sessions.rejected",
        "process.cpu.usage",
        "tomcat.threads.config.max",
        "jvm.classes.loaded",
        "hikaricp.connections.max",
        "hikaricp.connections.min",
        "jvm.classes.unloaded",
        "tomcat.global.error",
        "tomcat.sessions.active.current",
        "tomcat.sessions.alive.max",
        "jvm.gc.live.data.size",
        "tomcat.servlet.request.max",
        "hikaricp.connections.usage",
        "tomcat.threads.current",
        "tomcat.servlet.request",
        "hikaricp.connections.timeout",
        "process.files.open",
        "jvm.buffer.count",
        "jvm.buffer.total.capacity",
        "tomcat.sessions.active.max",
        "hikaricp.connections.acquire",
        "tomcat.threads.busy",
        "process.start.time",
        "tomcat.servlet.error"
    ]
}

正如您所看到的,列出了几个hikaricp.*指标jdbc.*,因此您的设置中一定有一些您尚未描述的内容导致了问题。我可以从日志输出中看到您正在使用 DevTools,并且某些东西在启动期间使用了连接池,但尝试重新创建此安排并没有重现问题。

我还可以从日志输出中看到某些内容触发了 Hikari 数据源的代理:

2018-05-29 18:39:14.327  INFO 326836 --- [  restartedMain] o.s.aop.framework.CglibAopProxy          : Method [void com.zaxxer.hikari.HikariConfig.seal()] is package-visible across different ClassLoaders and cannot get proxied via CGLIB: Declare this method as public or protected if you need to support invocations through the proxy.

从您到目前为止所描述的内容来看,我无法判断为什么会出现这种情况,但它可能与问题有关。

您能否提供重现该问题的最小样本?就目前情况而言,我们还有太多未知因素,无法在此方面取得有效进展。

0

我剥离了我们的项目并附上了拉链。父模块包含两个模块。 “master-service”实现了应用程序,因此它的目标文件夹包含可执行jar。请使用 Java 8 运行它。更高版本的 Java 抱怨找不到 JAXBException 类。

该应用程序定义了两个配置文件:local 和 DynamicDB。两个配置文件下都会出现该问题。您可以使用本地配置文件运行该应用程序。但是,您将无法使用 DynamicDB 配置文件运行该应用程序,因为我必须修改该代码才能为您提供一个工作示例。

此外,此应用程序将管理端点基本路径重新配置为“/”,因此指标在“/metrics”中可见。

问题-13295.zip

9

感谢您提供样品。它揭示了很多有关您的应用程序的信息,但未包含在您的描述中。关键是你已经排除了DataSourceAutoConfiguration。这样做的副作用是还会禁用提供数据源相关指标的 Bean 的自动配置。我们将通过将其分离到它自己的自动配置中来解决这个问题。同时,我相信您可以通过删除您的排除来解决您所看到的问题DataSourceAutoConfiguration,而只是依靠您自己的DataSourcebean 定义的存在来使其退出。

5

经过更多考虑后,我不太确定我们是否应该将其视为一个错误。根据当前的安排,声明您自己的DataSourcebean 和完全禁用 bean之间的行为存在差异DataSourceAutoConfiguration。如果我们将数据源元数据提供者的配置分离到单独的自动配置中,那么差异将会减少。可能有些用户故意DataSourceAutoConfiguration完全禁用,因为他们想利用这种差异。删除或减少它对他们来说将是一个重大改变。

@730alchemy 你禁用自动配置的原因是什么?查看您共享的代码,删除排除将为您提供所需的指标,同时还允许使用您自己的数据源定义。

1

我删除了排除DataSourceAutoConfiguration。当我调用metrics端点时,我现在会看到列出的 hikari 和 jdbc 连接指标。但是,应用程序无法将指标发送到 NewRelic。当应用程序尝试将指标发送到 NewRelic 时,它会记录以下错误:

ERROR 448048 --- [pool-1-thread-1] i.m.newrelic.NewRelicMeterRegistry       : failed to send metrics: {"error":"Error parsing JSON payload at event index 8"}

Spring Boot Actuator 参考文档指出,每个特定于 hikari 的指标都由池的名称标记,而我没有明确配置该名称。我认为这可能会导致解析错误,因此我为数据源配置了一个池名称,但这并没有解决错误...尽管它确实将错误消息从 更改为Error parsing JSON payload at event index 30...Error parsing JSON payload at event index 8也许这修复了一个解析错误,但又修复了另一个错误留下来?

RE:为什么我们禁用数据源自动配置......我不知道为什么这被排除。我与最初的开发人员交谈过,他几个月前编写了这个代码,但他不记得确切的原因。他记得数据源自动配置所做的不仅仅是创建数据源 bean,从而干扰了我们的自定义 jpa 配置,但他不记得确切的问题。

然而,那是 Spring Boot 的旧版本,事情已经发生了变化、改进等等……我们现在可以删除此排除并重新测试以确保没有回归,但是在传输到 NewRelic 时我们遇到了 JSON 解析问题。请注意,当向 NewRelic 发送不包含 jdbc 和 hikari 指标的有效负载时,应用程序不会抛出此错误。

6

RE:这是否是一个错误...DataSource配置与配置正交MetricRegistry。我不认为DataSource配置应该干扰用于的配置约定。根据 Actuator 参考文档,MetricRegistry 当前的配置约定是为在类路径上找到的每个受支持的实现添加一个注册表到组合中。MetricRegistryMetricRegistry

DataSource自动配置被禁用并且应用程序配置自己的时DataSourceDataSource实现位于类路径上。因此,我认为MetricRegistry自动配置应该遵循记录的约定并添加适当的注册表。

2

我认为 DataSource 配置不应干扰 MetricRegistry 使用的配置约定。

我同意,而且据我所知,不存在这样的干扰。

当禁用数据源自动配置并且应用程序配置自己的数据源时,数据源实现位于类路径上。因此,我认为 MetricRegistry 自动配置应该遵循记录的约定并添加适当的注册表。

这正是所发生的情况。正如您在开头描述中已经指出的那样,指标正在发送到 New Relic。由此我们可以推断 New Relic 仪表注册表已按预期自动配置。

问题不是仪表注册表被关闭,而是某些特定于数据源的仪表的注册已被关闭。当排除数据源自动配置时,它们将被关闭,因为数据源自动配置启用了它们的注册。

正如上面已经建议的,您可以通过不排除数据源自动配置来避免该问题。如果您出于某种原因希望排除自动配置,但继续公开与数据源相关的指标,则可以导入相关的配置类:

@Import(DataSourcePoolMetadataProvidersConfiguration.class)

或者,您可以提供自己的DataSourcePoolMetadataProviderbean。

无论哪种方式,此类 bean 的可用性都将允许DataSourcePoolMetricsAutoConfiguration为池的指标注册计量。

7

Spring Boot Actuator 参考文档指出,每个特定于 hikari 的指标都由池的名称标记,而我没有明确配置该名称。我认为这可能会导致解析错误,因此我为数据源配置了一个池名称,但这并没有解决错误...尽管它确实将错误消息从 Error parsing JSON payload at event index 30 更改为 Error parsing JSON事件索引 8 处的有效负载...也许这修复了一个解析错误,但仍然存在另一个错误?

我不确定索引的变化是否重要,因为它取决于发送的事件的批处理。设置池名称似乎会导致索引发生更改,这可能是巧合。

我猜想 Micrometer 创建发送到 New Relic 的 JSON 的方式存在问题,类似于https://github.com/micrometer-metrics/micrometer/issues/589。也许该问题的修复不完整?了解您正在使用的自定义标记值(如果有)会很有用。

/抄送@jkschneider

7

我在方法中设置了一个断点NewRelicMeterRegistry sendEvents来检查发送到 New Relic 的请求以及收到的错误消息。发送到 NewRelic 的 JSON 有效负载中,看起来有问题的部分是以下元素:

{
    "eventType": "hikaricpConnectionsPending",
    "value": NaN,
    "pool": "local-ds"
}

JSON lint 尝试解析“value”行时会引发错误。上述元素是有效负载中的索引 8,它与错误消息匹配。

ERROR 448048 --- [pool-1-thread-1] i.m.newrelic.NewRelicMeterRegistry       : failed to send metrics: {"error":"Error parsing JSON payload at event index 8"}

RE:自定义标签...我没有使用任何自定义标签

2

谢谢。在我看来,应该由https://github.com/micrometer-metrics/micrometer/commit/3d0f1fd80dc30032c5b31c0de433b1be9d5b1a09解决。该更改是在 Micrometer 1.0.3 中进行的,因此可能尚未解决该问题,因为您可能正在使用 1.0.4。

对于此问题的电表注册方面,我们有#13330。我认为剩下的问题需要作为千分尺问题来解决。不幸的是,我们无法将问题从一个存储库转移到另一个存储库。您能打开一个千分尺问题来尝试发货NaN吗?

7

感谢 Andy 帮助我解决了配置应用程序以发送 Hikari 指标的问题。

关于 Micrometer 发送到 New Relic 的 JSON 有效负载,我进一步挖掘并发现我们的部分代码库正在拉入旧版本的 Micrometer。当我修复此问题以获得 Micrometer 1.0.4 时,问题得到了解决。我们的 New Relic 帐户现在是 Hikari 连接池指标的自豪接收者。