Quarkus 中的路径解析
过去几周,我们经历了一段不寻常的颠簸。路径解析可能非常复杂,而在试图让事情变得更好时,我们却意外地让它们变得更糟!我们现在已经全部修复了,但您可能会注意到一些变化。希望这篇博文能清楚地说明这些变化是什么,它们意味着什么,以及您可以做什么来恢复一切,让它回到您想要的样子。
简而言之: 从 1.11.5.Final
和 1.12.1.Final
开始,前导斜杠在配置中很重要。因此,如果您使用 /endpoint
,该端点将从绝对根目录提供服务。如果您希望它相对于某个包含的存储桶,请省略前导斜杠。例如,quarkus.http.non-application-root-path
现在默认为 q
,它嵌套在 quarkus.http.root-path
下,与原始行为匹配。您可以使用绝对路径,例如 /q
,从绝对根目录(如果设置了 HTTP 根目录,则作为其同级)提供非应用程序端点。要完全移除非应用程序端点行为,请将 quarkus.http.non-application-root-path
设置为与 quarkus.http.root-path
相同的值。最万无一失的方法是使用变量:quarkus.http.non-application-root-path=${quarkus.http.root-path}
。
长话短说
曾经,Quarkus 为健康检查和指标等事物定义了其他端点。它们与应用程序定义的任何端点一起,从 quarkus.http.root-path
提供服务。这并不总是显而易见的,因为 quarkus.http.root-path
默认为 /
,使其几乎不可见。
随着这些端点的激增,我们开始担心污染应用程序端点命名空间,并考虑如何将这些非应用程序端点分组在一起,以避免与应用程序端点冲突,并使其更容易处理安全和访问策略。一些用户还询问我们是否可以从另一个端口提供这些非应用程序端点(我们还没有做到)。
第一步是将所有这些由扩展定义的端点分组在一起。这就是非应用程序端点路径的起源。此新路径的默认位置是 /q
,它嵌套在 HTTP 根路径下,就像其他端点一样。举例来说,效果是将 /health
移动到 /q/health
。
我们知道,移动某些端点(如指标和健康状况)会对已部署的应用程序和人类的肌肉记忆造成问题。为了缓解过渡,我们为其中一些端点添加了重定向,这样如果您访问 /metrics
,您将被重定向到 /q/metrics
。
非应用程序端点支持已在 1.11.0.Final
中发布。
然后事情开始变得糟糕。例如,一些云托管提供商只接受 200
作为健康的定义,所以重定向(一个 301
)没有达到预期的效果。关于如何关闭非应用程序端点以恢复先前行为,以及如何将特定端点移出此非应用程序端点集合,也存在一些困惑。
顺便说一句,我们陷入这种状况的原因还受到库行为差异的影响。例如,Vert.x 在创建路由时总是希望段以斜杠开头,而 JAX-RS 在 @Path
注释中实际上会忽略前导斜杠。习惯了 Vert.x 的开发者总是会添加前导斜杠,而使用 JAX-RS 的开发者则随便做什么,它就会神奇地奏效。
在 Quarkus 中,一个实现细节被意外暴露:扩展定义的非应用程序端点基于 Vert.x 路由。默认路径配置值以斜杠开头,以启用快速路由创建并允许简单的追加行为。在 Quarkus 的早期,没有什么表明这是一个坏主意,并且有 JAX-RS 经验的开发人员也没有任何警告,因为 JAX-RS 会处理它。
然而,现在我们面临的情况是,路径没有按人们预期的那样解析,而解决这种情况所需的配置更改要么不直观,要么会导致其他问题。我们最终将所有可能的配置排列组合放入一个电子表格中,以便我们可以并排查看组合不同配置值时会发生什么。结果并不理想。然而,这项练习使我们能够退一步,着眼于大局,评估需要改变什么才能让应用程序和非应用程序端点的行为符合您的需求。
虽然用于配置 Quarkus 中路径的配置属性集保持不变,但配置值的解释方式不同了。
-
端点路径配置的默认值现在是相对值。
/q
现在是q
,/metrics
现在是metrics
,依此类推。这意味着,开箱即用地,这些端点将相对于包含的根目录进行解析,这正是 JAX-RS 按规范所做的,也是我们认为大多数用户直观期望的。 -
显式配置值中的前导斜杠很重要。 我们知道您中的一些人想将端点移到特定位置,而表达这种意图的最一致的方式是允许您指定端点使用的确切 URI。如果您指定
/metrics
,您将在此处找到指标端点。
这些更新已经可用,并且随着 1.11.5.Final
和 1.12.1.Final
的发布,混乱应该已经平息。
请注意,非应用程序端点的便捷重定向仍然存在,但可以通过将 quarkus.http.redirect-to-non-application-root-path
设置为 false
来禁用它们。这一点完全没有改变。
配置路径的解析
让我们通过一些示例来了解在我们的新规则下路径是如何解析的。我们将从以下假设开始
-
我们有一个 Hello World 应用程序,它定义了
@ApplicationPath("/hello")
-
应用程序使用
@Path("world")
和@Path("/aliens")
定义了两个端点
我们最关心的配置属性是
-
quarkus.http.root-path
- HTTP 根路径。所有 Web 内容都相对于此根路径提供服务。 -
quarkus.http.non-application-root-path
- 非应用程序端点的根路径。
我们还将重点介绍一些值得关注的可配置非应用程序端点
-
quarkus.micrometer.export.prometheus.path
- Micrometer 指标端点的位置。 -
quarkus.smallrye-health.root-path
- 全面的健康端点位置。 -
quarkus.smallrye-health.liveness-path
- 活动端点位置。
让我们看看当我们开始调整参数时会发生什么。在下面的示例中,请注意配置中的标点符号,这将是它们行为方式的关键。
默认值
以下是默认配置值
-
quarkus.http.root-path=/
-
quarkus.http.non-application-root-path=q
-
quarkus.micrometer.export.prometheus.path=metrics
-
quarkus.smallrye-health.root-path=health
-
quarkus.smallrye-health.liveness-path=liveness
该配置(以及声明的应用程序端点)在我们的 Quarkus 应用程序以开发模式运行时,将导致以下有效 URL
请注意,在此示例中 quarkus.http.root-path
是隐藏的,因为它的值为 /
。
在这种情况下,存在便捷重定向,因为 quarkus.http.non-application-root-path
与 quarkus.http.root-path
不同。在此配置中,/metrics
将被重定向到 /q/metrics
。
更改 HTTP 根路径
让我们将 HTTP 根路径更改为 /root
,以便其对资源解析的影响可见
-
quarkus.http.root-path=/root
-
quarkus.http.non-application-root-path=q
-
quarkus.micrometer.export.prometheus.path=metrics
-
quarkus.smallrye-health.root-path=health
-
quarkus.smallrye-health.liveness-path=liveness
这将导致以下开发模式 URL
在这种情况下,也有便捷重定向,因为 quarkus.http.non-application-root-path
与 quarkus.http.root-path
不同。在此配置中,/root/metrics
将被重定向到 /root/q/metrics
。这与之前的行为一致,即非应用程序端点隐式相对于 HTTP 根路径。
移动非应用程序根路径 (/q)
让我们尝试一些以前无法做到的事情。我们将通过指定绝对路径 /q
将非应用程序端点移出 HTTP 根路径
-
quarkus.http.root-path=/root
-
quarkus.http.non-application-root-path=/q
-
quarkus.micrometer.export.prometheus.path=metrics
-
quarkus.smallrye-health.root-path=health
-
quarkus.smallrye-health.liveness-path=liveness
这将导致以下开发模式 URL
在这种情况下仍然存在便捷重定向,因为 quarkus.http.non-application-root-path
与 quarkus.http.root-path
不同。重定向的 URL 仍然相对于 HTTP 根目录,因此 /root/metrics
将被重定向到 /q/metrics
。
移动单独的非应用程序端点 (/metrics 和 /liveness)
这是另一个以前不可能的配置。我们可以将可配置的非应用程序端点单独移动到指定的绝对路径,在本例中具体是 /metrics
和 /liveness
-
quarkus.http.root-path=/root
-
quarkus.http.non-application-root-path=/q
-
quarkus.micrometer.export.prometheus.path=/metrics
-
quarkus.smallrye-health.root-path=health
-
quarkus.smallrye-health.liveness-path=/liveness
这将导致以下开发模式 URL
在这种情况下仍然存在便捷重定向,因为 quarkus.http.non-application-root-path
与 quarkus.http.root-path
不同。但是,这些重定向仅适用于受非应用程序端点根目录控制的非应用程序端点。我们基本上已从该根目录中删除了指标和活动端点,因此它们不会被重定向。在此配置中,如果您请求 /root/health
,它将被重定向到 /q/health
。不会为 /root/health/liveness
或 /root/metrics
提供重定向。
移除非应用程序端点根目录
你们中的一些人问过如何完全关闭这些非应用程序端点根目录的东西。最好清晰地表达您的意图。要禁用非应用程序端点,请使其与 HTTP 根路径相同。本质上,您是在告诉运行时“从 HTTP 根目录提供所有非应用程序端点”。此示例使用变量来确保值保持不变
-
quarkus.http.root-path=/root
-
quarkus.http.non-application-root-path=${quarkus.http.root-path}
-
quarkus.micrometer.export.prometheus.path=metrics
-
quarkus.smallrye-health.root-path=health
-
quarkus.smallrye-health.liveness-path=liveness
这将导致以下开发模式 URL
在这种情况下,没有便捷重定向,因为非应用程序端点行为已完全禁用。
连锁效应
在大多数情况下,我们希望这会是透明的。在此过程中,我们发现了一些非常不一致的路径处理,这使我们相信许多(甚至大多数)这些值从未被自定义过。
如果您自定义了 HTTP 根路径,您最有可能看到行为上的变化。在这种情况下,我们希望新的规则和上面的示例能帮助您了解如何调整您的配置以使一切按照您想要的方式运行。
扩展作者将看到最大的变化。已更新编写扩展指南,以描述用于创建非应用程序端点的构建项的变化。但是,总的规则是避免自行构造端点路径,并依赖 NonApplicationRootPathBuildItem
和 HttpRootPathBuildItem
来为您构建它们。