我对Spring Framework有点陌生。我有一个用Spring(4.2.1)编写的Web应用程序。我正在尝试使用Micrometer库公开指标,并将使用Prometheus进行抓取。
应用程序的相关结构是这样的:-核心模块(JAR)-Web服务模块(WAR)
我创建了一个PrometheusService类,它是在核心模块中定义的bean。在bean内定义的是PrometheusMeterRegistry
和Counter
:
@Service
public class PrometheusService {
private static PrometheusMeterRegistry registry = new PrometheusMeterRegistry(PrometheusConfig.DEFAULT);
private static Counter newAssetCounter = Counter
.builder("new_asset_counter")
.description("count of created assets")
.tags("region", "na")
.register(registry);
public PrometheusService() {
new JvmMemoryMetrics().bindTo(registry);
new DiskSpaceMetrics(new File("/")).bindTo(registry);
new ProcessorMetrics().bindTo(registry);
new UptimeMetrics().bindTo(registry);
}
public static PrometheusMeterRegistry getRegistry() {
return registry;
}
public Counter getNewAssetCounter() {
return this.newAssetCounter;
}
}
我创建了MetricsResource,这是一个暴露[/ Https]端点的HttpServlet。尝试@Autowire
PrometheusService Bean时,此处始终为null。快速搜索告诉我HttpServlet不是由Spring管理的。如果我想@Autowire
,则需要添加如下内容:
SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(webApplicationContext);
现在,我能够@Autowire
Servlet中的PrometheusService bean。
bean中定义的Counter
在核心模块内递增。 MetricsResource doGet
方法写入存储在PrometheusMeterRegistry
中的度量。
,是在/ metrics端点处@WebServlet("/metrics") public class MetricsResource extends HttpServlet { private PrometheusService promService; // @Autowired private PrometheusMeterRegistry registry; @Override public void init() throws ServletException { super.init(); // SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(webApplicationContext); // promService = (PrometheusService) getServletContext().getAttribute("prometheusService"); // WebApplicationContext context = WebApplicationContextUtils.getWebApplicationContext(getServletContext()); // AutowireCapableBeanFactory ctx = context.getAutowireCapableBeanFactory(); // ctx.autowireBean(this); } @Override protected void doGet(final HttpServletRequest req, final HttpServletResponse resp) throws IOException { resp.setStatus(HttpServletResponse.SC_OK); resp.setContentType(TextFormat.CONTENT_TYPE_004); registry = promService.getRegistry(); Writer writer = resp.getWriter(); try { registry.scrape(writer); writer.flush(); } finally { writer.close(); } } }
尽管有问题
Counter
的值始终为0。 无论是@Autowired还是我手动尝试获取bean。
这怎么可能?我的PrometheusService Bean是单例。甚至PrometheusMeterRegistry和Counter也被标记为静态,那么为什么在servlet中得到另一个对象?经过更多搜索后,我发现Spring将为每个容器创建一个单例bean
。所以我假设这里发生的是有两个容器或上下文。主应用程序上下文和servlet上下文。我尝试过的一些事情:使PrometheusService实现ApplicationContextAware
使用实现ApplicationContextAware
并返回Bean的ServiceLocator类将上下文参数添加到web.xml在app-context.xml中使用ServletContextAttributeExporter
使用WebApplicationContextUtils.getRequiredWebApplicationContext(config.getServletContext())
我继续获得该对象的新实例。我要做的就是能够使用Micrometer创建和公开自定义指标。我的方法有缺陷吗?如何从HttpServlet中访问正确的bean?
Spring dependency injection to other instancehttp://senthadev.com/sharing-spring-container-between-modules-in-a-web-application.htmlSpring dependency injection to other instanceApplicationContext and ServletContext
我对Spring Framework有点陌生。我有一个用Spring(4.2.1)编写的Web应用程序。我正在尝试使用Micrometer库公开指标,并将使用Prometheus进行抓取。相关的...
尝试processInjectionBasedOnServletContext(Object target, ServletContext servletContext)
。