简体   繁体   English

Spring Boot Actuator 不带 Spring Boot

[英]Spring Boot Actuator without Spring Boot

I've been working on a Spring/Spring MVC application and I'm looking to add performance metrics.我一直在开发 Spring/Spring MVC 应用程序,我希望添加性能指标。 I've come across Spring Boot Actuator and it looks like a great solution.我遇到过 Spring Boot Actuator,它看起来是一个很好的解决方案。 However my application is not a Spring Boot application.但是我的应用程序不是 Spring Boot 应用程序。 My application is running in a traditional container Tomcat 8.我的应用程序在传统容器中运行 Tomcat 8.

I added the following dependencies我添加了以下依赖项

// Spring Actuator
compile "org.springframework.boot:spring-boot-starter-actuator:1.2.3.RELEASE"

I created the following config class.我创建了以下配置 class。

@EnableConfigurationProperties
@Configuration
@EnableAutoConfiguration
@Profile(value = {"dev", "test"})
@Import(EndpointAutoConfiguration.class)
public class SpringActuatorConfig {

}

I even went as far as adding @EnableConfigurationProperties on every configuration class as suggested on another post on StackOverflow.我什至按照 StackOverflow 上另一篇文章的建议,在每个配置 class 上添加@EnableConfigurationProperties However that didn't do anything.然而那并没有起到任何作用。 The endpoints are still not being created and return 404s.端点仍未创建并返回 404。

First let's clarify that you cannot use Spring Boot Actuator without using Spring Boot.首先让我们澄清一下,如果不使用 Spring Boot,就不能使用 Spring Boot Actuator。

I was wrong about not being able to it without Spring Boot.如果没有 Spring Boot,我就无法做到这一点,我错了。 See @stefaan-neyts answer for an example of how to do it.有关如何执行此操作的示例,请参阅 @stefaan-neyts 答案。

I created a sample project to show how you could convert a basic SpringMVC application using a minimal amount of Spring Boot auto-configuration.我创建了一个示例项目来展示如何使用最少的 Spring Boot 自动配置来转换基本的 SpringMVC 应用程序。

Original source: http://www.mkyong.com/spring-mvc/gradle-spring-mvc-web-project-example原始来源: http : //www.mkyong.com/spring-mvc/gradle-spring-mvc-web-project-example

Converted source: https://github.com/Pytry/minimal-boot-actuator转换源: https : //github.com/Pytry/minimal-boot-actuator

I could have completely removed the dispatcher-servlet.xml and the web.xml files, but I kept them to show how to perform as minimal a change as possible and to simplify converting more complex projects.我本可以完全删除 dispatcher-servlet.xml 和 web.xml 文件,但我保留它们是为了展示如何执行尽可能少的更改并简化更复杂项目的转换。

Here is a list of steps I took to convert.这是我进行转换所采取的步骤列表。

Conversion Process转换过程

  • Add a Java Configuration file annotated with @SpringBootApplication添加一个用@SpringBootApplication注解的Java配置文件
  • Add the Application configuration file as a bean to the traditional xml configuration ( added it just after the context scan).将 Application 配置文件作为 bean 添加到传统的 xml 配置中(在上下文扫描之后添加)。
  • Move view resolvers into Application java configuration.将视图解析器移动到应用程序 java 配置中。

    Alternatively, add the prefix and suffix to application.properties.或者,将前缀和后缀添加到 application.properties。 You can then inject them with @Value in your application, or delete it entirely and just use the provided spring boot view resolver.然后,您可以在应用程序中使用 @Value 注入它们,或者将其完全删除并仅使用提供的 Spring Boot 视图解析器。 I went with the former.我和前者一起去了。

  • Removed Default context listener from the spring context xml.从 spring 上下文 xml 中删除了默认上下文侦听器。

    This is important!这个很重要! Since spring boot will provide one you will get an "Error listener Start" exception if you do not.由于 spring boot 将提供一个,如果您不提供,您将收到“错误侦听器启动”异常。

  • Add the spring boot plugin to your build script dependencies (I was using gradle)将 spring boot 插件添加到您的构建脚本依赖项中(我使用的是 gradle)

  • Add a mainClassName property to the build file, and set to an empty String (indicates not to create an executable).将 mainClassName 属性添加到构建文件,并设置为空字符串(表示不创建可执行文件)。

  • Modify dependencies for spring boot actuator修改 spring boot 执行器的依赖项

You can use actuator without spring boot.您可以使用没有弹簧靴的执行器。 Add this to pom.xml将此添加到 pom.xml

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-actuator</artifactId>
    <version>1.3.5.RELEASE</version>
</dependency>

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-web</artifactId>
    <version>4.3.5.RELEASE</version>
</dependency>

And then in your config class然后在你的配置类中

@Configuration
@EnableWebMvc
@Import({
        EndpointAutoConfiguration.class , PublicMetricsAutoConfiguration.class , HealthIndicatorAutoConfiguration.class
})
public class MyActuatorConfig {

    @Bean
    @Autowired
    public EndpointHandlerMapping endpointHandlerMapping(Collection<? extends MvcEndpoint> endpoints) {
        return new EndpointHandlerMapping(endpoints);
    }

    @Bean
    @Autowired
    public EndpointMvcAdapter metricsEndPoint(MetricsEndpoint delegate) {
        return new EndpointMvcAdapter(delegate);
    }
}

And then you can see the metrics in your application然后你可以在你的应用程序中看到指标

http://localhost:8085/metrics http://localhost:8085/metrics

执行器终点

Allthough it is not a good idea to use Spring Boot features without Spring Boot, it is possible!尽管在没有 Spring Boot 的情况下使用 Spring Boot 功能不是一个好主意,但这是可能的!

For example, this Java configuration makes Spring Boot Actuator Metrics available without using Spring Boot:例如,此 Java 配置使 Spring Boot Actuator Metrics 在不使用 Spring Boot 的情况下可用:

import java.util.Collection;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.actuate.autoconfigure.EndpointAutoConfiguration;
import org.springframework.boot.actuate.autoconfigure.PublicMetricsAutoConfiguration;
import org.springframework.boot.actuate.endpoint.MetricsEndpoint;
import org.springframework.boot.actuate.endpoint.mvc.EndpointHandlerMapping;
import org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter;
import org.springframework.boot.actuate.endpoint.mvc.MvcEndpoint;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;

@Configuration
@Import({ EndpointAutoConfiguration.class, PublicMetricsAutoConfiguration.class })
public class SpringBootActuatorConfig {

    @Bean
    @Autowired
    public EndpointHandlerMapping endpointHandlerMapping(Collection<? extends MvcEndpoint> endpoints) {
        return new EndpointHandlerMapping(endpoints);
    }

    @Bean
    @Autowired
    public EndpointMvcAdapter metricsEndPoint(MetricsEndpoint delegate) {
        return new EndpointMvcAdapter(delegate);
    }
}

The Maven dependency: Maven 依赖:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-actuator</artifactId>
    <version>1.3.5.RELEASE</version>
</dependency>

Though the answer is already accepted, I thought of updating my experience.虽然答案已经被接受,但我想更新我的经验。 I did not want to convert my application to spring boot using @SpringBootApplication .我不想使用@SpringBootApplication将我的应用程序转换为 spring boot。 Refer to another question where I have mentioned the bare minimum code required.请参阅另一个问题,其中我提到了所需的最低限度代码。

As we already have Spring Boot Actuator 2.x, a recipe to include actuator to an existing Spring MVC project can look like this:由于我们已经有了 Spring Boot Actuator 2.x,将执行器包含到现有 Spring MVC 项目中的方法可能如下所示:

@Configuration
@Import({
        EndpointAutoConfiguration.class,
        HealthIndicatorAutoConfiguration.class,

        InfoEndpointAutoConfiguration.class,
        HealthEndpointAutoConfiguration.class,

        WebEndpointAutoConfiguration.class,
        ServletManagementContextAutoConfiguration.class,
        ManagementContextAutoConfiguration.class,
})
@EnableConfigurationProperties(CorsEndpointProperties.class)
class ActuatorConfiguration {

    @Bean //taken from WebMvcEndpointManagementContextConfiguration.class
    public WebMvcEndpointHandlerMapping webEndpointServletHandlerMapping(WebEndpointsSupplier webEndpointsSupplier,
                                                                         ServletEndpointsSupplier servletEndpointsSupplier, ControllerEndpointsSupplier controllerEndpointsSupplier,
                                                                         EndpointMediaTypes endpointMediaTypes, CorsEndpointProperties corsProperties,
                                                                         WebEndpointProperties webEndpointProperties) {
        List<ExposableEndpoint<?>> allEndpoints = new ArrayList<>();
        Collection<ExposableWebEndpoint> webEndpoints = webEndpointsSupplier.getEndpoints();
        allEndpoints.addAll(webEndpoints);
        allEndpoints.addAll(servletEndpointsSupplier.getEndpoints());
        allEndpoints.addAll(controllerEndpointsSupplier.getEndpoints());
        EndpointMapping endpointMapping = new EndpointMapping(webEndpointProperties.getBasePath());
        return new WebMvcEndpointHandlerMapping(endpointMapping, webEndpoints, endpointMediaTypes,
                corsProperties.toCorsConfiguration(),
                new EndpointLinksResolver(allEndpoints, webEndpointProperties.getBasePath()));
    }

    @Bean
    DispatcherServletPath dispatcherServletPath() {
        return () -> "/";
    }

}

I did include我确实包括

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-actuator-autoconfigure</artifactId>
        <version>2.1.18.RELEASE</version>
    </dependency>

for compatibility with the baseline Spring version I've been using (5.1.19.RELEASE)为了与我一直使用的基线 Spring 版本兼容 (5.1.19.RELEASE)

You will need to convert your application to Spring Boot if you want to use the components that plug into it.如果要使用插入其中的组件,则需要将应用程序转换为 Spring Boot。 There is a section named Convert an existing application to Spring Boot under the Spring Boot docs that you will want to review.您需要查看的 Spring Boot 文档下有一个名为 Convert an existing application to Spring Boot 的部分。 I have not done this myself but I use Spring Boot and it is relatively simple to configure so hopefully you can get it from here.我自己没有这样做,但我使用 Spring Boot,它的配置相对简单,所以希望你能从这里得到它。

If your objective is to create an endpoint with metrics for Prometheus aka OpenMetrics, you can use the Prometheus JVM client which is compatible with Spring framework.如果您的目标是为 Prometheus aka OpenMetrics 创建一个具有指标的端点,您可以使用与 Spring 框架兼容的Prometheus JVM 客户端

Add dependency:添加依赖:

    <dependency>
      <groupId>io.prometheus</groupId>
      <artifactId>simpleclient_servlet</artifactId>
      <version>0.16.0</version>
    </dependency>

To collect metrics of requests, add as first filter in web-app/WEB-INF/web.xml :要收集请求指标,请在web-app/WEB-INF/web.xml中添加为第一个过滤器:

  <filter>
    <filter-name>prometheusFilter</filter-name>
    <filter-class>io.prometheus.client.filter.MetricsFilter</filter-class>
    <init-param>
      <param-name>metric-name</param-name>
      <param-value>webapp_metrics_filter</param-value>
    </init-param>
  </filter>
  <filter-mapping>
    <filter-name>prometheusFilter</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>

To expose metrics as HTTP endpoint, add servlet:要将指标公开为 HTTP 端点,请添加 servlet:

  <servlet>
    <servlet-name>prometheus</servlet-name>
    <servlet-class>io.prometheus.client.exporter.MetricsServlet</servlet-class>
  </servlet>
  <servlet-mapping>
    <servlet-name>prometheus</servlet-name>
    <url-pattern>/metrics</url-pattern>
  </servlet-mapping>

After that you can see the metrics on the /metrics endpoint.之后,您可以在/metrics端点上看到指标。

Time passes, we have Spring 6, SpringBoot 3, JakartaEE as a baseline, but people are still looking to add actuator to legacy spring applications.时间流逝,我们有 Spring 6、SpringBoot 3、JakartaEE 作为基准,但人们仍在寻求向遗留 spring 应用程序添加执行器。 So a small update: spring + actuator without spring-boot. In fact not much changes (and the changes have already been pointed out).所以一个小的更新:spring + 没有 spring-boot 的执行器。实际上变化不大(并且已经指出了变化)。

The dependencies依赖项

    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-webmvc</artifactId>
        <version>6.0.3</version>
    </dependency>
    <dependency>
       <groupId>jakarta.servlet</groupId>
       <artifactId>jakarta.servlet-api</artifactId>
       <version>6.0.0</version>
       <scope>provided</scope>
    </dependency>
    
    <dependency>
       <groupId>org.springframework.boot</groupId>
       <artifactId>spring-boot-actuator-autoconfigure</artifactId>
       <version>3.0.1</version>
    </dependency>

The actuator configuration执行器配置

@Configuration
@ImportAutoConfiguration({
    EndpointAutoConfiguration.class,
    WebEndpointAutoConfiguration.class,
    ServletManagementContextAutoConfiguration.class,
    ManagementContextAutoConfiguration.class,

    HealthContributorAutoConfiguration.class,

    InfoEndpointAutoConfiguration.class,
    HealthEndpointAutoConfiguration.class,

    HeapDumpWebEndpointAutoConfiguration.class,
    ThreadDumpEndpointAutoConfiguration.class,
    LoggersEndpointAutoConfiguration.class,
    PrometheusMetricsExportAutoConfiguration.class,
})
@EnableConfigurationProperties(CorsEndpointProperties.class)
class ActuatorConfiguration {

    @Bean //taken from WebMvcEndpointManagementContextConfiguration.class
    public WebMvcEndpointHandlerMapping webEndpointServletHandlerMapping(WebEndpointsSupplier webEndpointsSupplier,
        ServletEndpointsSupplier servletEndpointsSupplier, ControllerEndpointsSupplier controllerEndpointsSupplier,
        EndpointMediaTypes endpointMediaTypes, CorsEndpointProperties corsProperties,
        WebEndpointProperties webEndpointProperties) {
        List<ExposableEndpoint<?>> allEndpoints = new ArrayList<>();
        Collection<ExposableWebEndpoint> webEndpoints = webEndpointsSupplier.getEndpoints();
        allEndpoints.addAll(webEndpoints);
        allEndpoints.addAll(servletEndpointsSupplier.getEndpoints());
        allEndpoints.addAll(controllerEndpointsSupplier.getEndpoints());
        EndpointMapping endpointMapping = new EndpointMapping(webEndpointProperties.getBasePath());
        return new WebMvcEndpointHandlerMapping(endpointMapping,
            webEndpoints,
            endpointMediaTypes,
            corsProperties.toCorsConfiguration(),
            new EndpointLinksResolver(allEndpoints, webEndpointProperties.getBasePath()),
            true);
    }

    @Bean
    DispatcherServletPath dispatcherServletPath() {
        return () -> WebInitializer.APPLICATION_ROOT;
    }

}

The example is easy to run directly from maven jetty plugin ( mvn jetty:run-war ).该示例很容易直接从 maven jetty 插件 ( mvn jetty:run-war ) 运行。

            <plugin>
                <groupId>org.eclipse.jetty</groupId>
                <artifactId>jetty-maven-plugin</artifactId>
                <version>11.0.13</version>
            </plugin>

最后的结果

你犯了一个错误,没有在你的代码中引入 @springboot 注释。当你添加 @springboot 时,编译器会自动将其视为引导程序,并为其添加所需的依赖文件和执行器依赖文件

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM