[spring-projects/spring-boot]为 AbstractRoutingDataSource 的解析目标提供指标
回答
根据这个审查意见,我认为我们这里需要考虑的主要问题是如何命名每个目标DataSource
。有几个场景需要考虑:
- 目标
DataSource
是单个 的目标AbstractRoutingDataSource
。 - 一个target
DataSource
是多个s的targetAbstractRoutingDataSource
。 - A
DataSource
既是顶级 bean,又是单个 的目标AbstractRoutingDataSource
。 - A
DataSource
既是顶级 bean,又是多个AbstractRoutingDataSource
s 的目标。
当目标DataSource
也是一个bean时(场景3和4),我认为它的name
标签应该继续是它的bean名称。这将确保与 2.4 及更早版本的向后兼容性。这将需要不同的标签来显示其路由信息。当它DataSource
是单个路由数据源的目标时,这个新标签的值可以是路由器的bean名称和路由键的组合。当DataSource
是多个路由数据源的目标时,理想情况下,该值将传达该信息。我们仅限于 a String
,因此我们必须界定每个值。从理论上讲,In bean 的名称可以是您想要的任何名称,因此目前还不清楚什么是好的分隔符。
当目标DataSource
只是一个目标时(场景 1 和 2),我们需要为其指定一个唯一的名称。路由键仅保证在路由数据源范围内唯一。我们需要在整个应用程序中唯一的东西,这样我们就不能单独使用路由键。路由数据源的 bean 名称在整个应用程序中是唯一的,因此我们可以将路由数据源的 bean 名称与路由键结合起来。这样做的缺点是名称标签的值将具有不同的格式,具体取决于目标是否也作为 bean 公开。
上面描述的四种场景可以映射到以下 bean:
- ds3
- dsFour
- 路由器一
- key1 -> dsOne
- key2 -> dsTwo
- key3 -> dsThree
- key4 -> dsFour
- 路由器二号
- key1 -> dsTwo
- key2 -> dsFour
dsThree
将被标记为name -> dsThree
和routing -> routerOne:key3
。
dsFour
将被标记为name -> dsFour
并将routing -> routerOne:key4,routerTwo:key2
dsOne
被标记为name -> routerOne:key1
并将routing -> routerOne:key1
dsTwo
被标记为name -> routerOne:key2,routerTwo:key1
和routing -> routerOne:key2,routerTwo:key1
其中,我唯一真正满意的是dsThree
。dsFour
如果我们能够确定在值中使用的良好分隔符,也可能没问题routing
。和的值相同,dsOne
感觉dsTwo
有点奇怪。随着名字变长,感觉真的很奇怪。name
routing
dsTwo
@wilkinsona 感谢您深入思考命名以及“多个路由 DS 中的相同 DS”情况。
其中,我唯一对 dsThree 感到非常满意。如果我们能够确定在路由值中使用的良好分隔符,dsFour 也可能没问题。 dsOne 和 dsTwo 的名称和路由值相同,感觉有点奇怪。随着名称变长,dsTwo 感觉真的很奇怪。
我同意以上所有内容。是的,在 DS 不是注册 bean 的情况下,路由信息就是名称,因此两个标签将是相同的。是的,随着它变得越来越长,它会变得不稳定。但这还不是最糟糕的事情,我很好奇这种情况发生的频率。
至于好的分隔符,Micrometer 中确实没有 bean 名称限制,也没有标签值限制。我在千分尺中挖了一点,看看那里是否有任何方向。我们可以选择一些合理的东西,然后将其配置为分隔符未涵盖的“一个”情况:)
我们今天讨论了这个问题,并一致认为上述标签值非常粗糙,不是我们想要实现的。我们讨论了一种替代方案,其中用户必须实现策略接口来为目标数据源提供标签。我们担心这个策略接口可能必须非常复杂并提供相当多的上下文,例如:
- 路由数据源的bean名称
- 路由数据源
- 目标数据源
- 目标数据源的路由键
我们还不相信这样的策略界面能够提供比用户为每个目标数据源绑定一些仪表本身更多的功能。我们将后退一步,在未来的版本中重新审视这一点。它可能只是一个文档问题,或者我们可能会以一些自动配置和标签策略接口的形式进行一些增强,或者只是一些帮助器 API,使用户代码更容易直接绑定一些仪表。
@wilkinsona 是否已经存在相同问题的问题org.springframework.r2dbc.connection.lookup.AbstractRoutingConnectionFactory
?一旦我开始AbstractRoutingConnectionFactory
在我的项目中使用,我就会丢失端点r2dbc.pool.*
公开的所有指标/actuator/metrics
。
我不认为 R2DBC 方面存在问题。目标连接工厂没有访问器,因此任何问题都将在 Spring 框架更改时被阻止。就目前情况而言,我认为我们没有理由要求进行这样的更改,因为 R2DBC 将面临与上述 JDBC 相同的标记挑战。
如果您对目标连接工厂(或使用 JDBC 的目标数据源)的指标感兴趣,我建议将它们公开为 beans,然后拥有@Primary
使用它们的路由连接工厂或数据源。
即使现在,当使用 AbstractRoutingDatasource 时,如果我不将其注册为 bean,我是否无法获取指标?
如果它不是一个 bean,Actuator 将不知道它的存在。在这种情况下,您可以使用 Micrometer API 手动注册指标。或者,您可以按照上面的建议进行操作。
AbstractRoutingDatasource 是 bean。
我的意思是如何将所有目标数据源注册到指标。 :)
@wilkinsona 我正在尝试获取抽象路由数据源的池信息,但 hikari 数据源池为空。当我在数据源上执行 getConnection 时,它就变得可用。您能否更新我如何记录抽象路由数据源池周围的指标。我想使用后台运行线程手动将它们暴露给普罗米修斯。
@sahilkamboj334 请在 Stack Overflow 上提出您的问题,并提供一个完整但最小的示例来说明您正在尝试执行的操作。
我们正在清理问题跟踪器并关闭我们没有看到太多需要解决的问题。如果您认为此问题不应该被关闭,请随时发表评论并提供其他理由。
不确定对已关闭的票发表评论是否可以,但因为
如果您认为此问题不应该被关闭,请随时发表评论并提供其他理由。
我认为过去已经完成了一些工作来自动配置已解决目标的运行状况端点AbstractRoutingDataSource
,并且确实感觉缺少指标。当切换到写入器-读取器基础设施或从 1 到多个分片等时,您可能会丢失指标。并且您需要进行一些挖掘才能理解为什么会发生这种情况。
在我们的例子中,我们最终手动注册了所有已解析的数据源,但让自动配置处理它,就像它为健康所做的那样,会简化它。
getResolvedDataSources()
至少对于 Hikari 来说,如果传入的数据源是路由数据源,是否可以只使用它? (参考:https://github.com/spring-projects/spring-boot/blob/8fa318453f2e3f128557350eb975fd68d356375f/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate /autoconfigure/metrics/jdbc/DataSourcePoolMetricsAutoConfiguration.java#L140)
@mathieufortin01 不幸的是,如果没有解决上述标记问题,我们就没有办法恢复这一点。就目前情况而言,手动绑定每个目标是最好的选择。
@wilkinsona 感谢您的及时回复。在这种情况下,如果指标自动配置遇到路由数据源,它是否可以记录它不会为其目标注册指标的事实(并且应该手动完成)?我认为这可以帮助推动人们找到正确的解决方案,但不确定此类日志是否是项目中的典型日志。
谢谢你的建议。不幸的是,我们试图避免这样的日志消息,因为它们会增加相当多的复杂性。例如,如果我们在遇到路由数据源时开始记录这样的消息,那么已经为所有目标绑定了指标的用户将很合理地不希望记录它。然后,我们要么必须尝试检测这种情况,要么提供配置属性来禁用日志消息。