在 Spring Boot API 的 Prometheus 指标中,有一个非常神秘的 root“端点”,有时似乎会被调用。这看起来就像有人在探测我们的 API,但端点不存在。真正奇怪的部分是,我不知道如何调用这个“URI”,因为它不是以正斜杠开头(
/
)?我们还在 pod 日志中看到此请求,但在入口控制器日志中看不到。它可能从哪里来?
来自 WebMvcTags 在 servlet Filter 处理请求时始终将“root”报告为 uri #17147
在 Spring-MVC Boot 应用程序中,如果在正常情况下映射到 Spring-MVC 控制器的请求由 servlet Filter 处理,则
指标始终使用根 uri 进行报告。例如,在使用 Spring Security 时就会发生这种情况。http.server.requests
原因是在这些情况下使用请求的路径信息,该信息始终为 null,因为WebMvcTags
被映射为默认 servlet:整个路径将出现在 servlet 路径中。DispatcherServlet
Spring Boot团队的回答:
团队再次讨论了这个问题,我们认为我们无法解决这个问题。
- 正如所解释的,从请求中获取 servlet 路径会导致指标爆炸式增长
- 其他路径(如过滤器映射路径)将没有用
- 我们不会调用 MVC 基础设施来映射该请求,因为它会产生安全问题并且可能会涉及很多(CORS 支持、拦截器)
此外,获取控制器映射并没有真正的帮助。如果请求确实很慢并且处理请求的过滤器出现错误,我们将报告控制器路径模式并使开发人员对其应用程序的行为不当部分感到困惑。也许 Servlet 过滤器名称在这里会更有用,但是无法在过滤器链中获取该名称,并且该信息不会真正映射到 uri 标记。
因此,我们将关闭此问题。
我遇到了同样的问题,很头疼。事实证明,在我的例子中,@Timing 注释被附加到我所有的其余控制器上,这些控制器悄悄地覆盖了执行器提供的默认 http 指标。
找到解决方案。 我添加了一个高优先级过滤器, 在过滤器中,我强制将 URL 属性包含在请求中。也许不完美,但它有效
属性名称取自 WebMvcTags.uri();
过滤器类
@AllArgsConstructor
public class MetricHandlingFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
if (request.getAttribute(HandlerMapping.BEST_MATCHING_PATTERN_ATTRIBUTE) == null) {
request.setAttribute(HandlerMapping.BEST_MATCHING_PATTERN_ATTRIBUTE, request.getRequestURI());
}
filterChain.doFilter(request, response);
}
}
配置类
@Configuration
@AllArgsConstructor
public class FilterConfiguration {
private final AutowireCapableBeanFactory beanFactory;
@Bean
public FilterRegistrationBean<MetricHandlingFilter> filterRegistration() {
MetricHandlingFilter handlingFilter = new MetricHandlingFilter();
beanFactory.autowireBean(handlingFilter);
FilterRegistrationBean<MetricHandlingFilter> registrationBean = new FilterRegistrationBean<>(handlingFilter);
registrationBean.setOrder(Integer.MIN_VALUE); //high priority
return registrationBean;
}
}