Spring Boot提供的端点(Endpoints)

https://docs.spring.io/spring-boot/docs/3.2.0/reference/htmlsingle/#actuator.endpoints

Actuator端点允许你监视和与你的应用程序进行交互。Spring Boot包含了许多内置端点,并允许你添加自己的端点。例如,health 端点提供了基本的应用程序健康信息。

你可以启用或禁用每个单独的端点,并通过HTTP或JMX将它们暴露出来(使它们可以通过远程访问)。当端点既被启用又被暴露时,它被认为是可用的。内置端点仅在它们可用时自动配置。大多数应用程序选择通过HTTP进行暴露,其中端点的ID和/actuator前缀映射到URL。例如,默认情况下,health 端点映射到/actuator/health

以下是与技术无关的可用端点:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

如果你的应用程序是一个Web应用程序(Spring MVC、Spring WebFlux或Jersey),你可以使用以下额外的端点:
在这里插入图片描述

启用端点(Enabling Endpoints)

默认情况下,除shutdown之外的所有端点都是启用的。要配置端点的启用状态,请使用management.endpoint.<id>.enabled属性。以下示例启用了shutdown端点:

management.endpoint.shutdown.enabled=true

如果你希望端点的启用状态是选择性的(即需要显式启用),而不是默认启用的,可以将management.endpoints.enabled-by-default属性设置为false,并使用各个端点的启用属性来显式启用它们。以下示例启用了info端点并禁用了所有其它端点:

management.endpoints.enabled-by-default=false
management.endpoint.info.enabled=true

注意:被禁用的端点将从应用程序上下文中完全移除。如果你只想改变端点暴露所使用的技术,请使用includeexclude属性。

暴露端点

默认情况下,只有健康端点通过HTTP和JMX暴露。由于端点可能包含敏感信息,因此你应该仔细考虑何时暴露它们。

要改变暴露哪些端点,请使用以下与技术相关的includeexclude 属性:
在这里插入图片描述

include属性列出了暴露的端点的ID。exclude属性列出了不应暴露的端点的ID。exclude属性优先于include属性。你可以使用端点ID的列表来配置includeexclude属性。

例如,要仅通过JMX暴露healthinfo 端点,请使用以下属性:

management.endpoints.jmx.exposure.include=health,info

*可用于选择所有端点。例如,要通过HTTP暴露所有端点,但除了envbeans端点,请使用以下属性:

management.endpoints.web.exposure.include=*
management.endpoints.web.exposure.exclude=env,beans

注意*在YAML中具有特殊含义,因此如果你想要包含(或排除)所有端点,请确保添加引号。

注意:如果你的应用程序公开暴露,强烈建议你还要保护你的端点。

提示:如果你想要实现自己的端点暴露策略,你可以注册一个EndpointFilter bean。

安全

出于安全原因,默认情况下只有/health端点通过HTTP暴露。你可以使用management.endpoints.web.exposure.include属性来配置暴露的端点。

注意:在设置management.endpoints.web.exposure.include之前,请确保暴露的Actuator不包含敏感信息,或者通过将它们放在防火墙后面或使用类似Spring Security的东西来保护它们。

如果Spring Security在类路径上,并且没有其它SecurityFilterChain bean存在,则Spring Boot自动配置会保护除/health之外的所有Actuator。如果你定义了一个自定义的SecurityFilterChain bean,Spring Boot自动配置会后退并让你完全控制Actuator的访问规则。

如果你希望为HTTP端点配置自定义安全性(例如,只允许具有特定角色的用户访问它们),Spring Boot提供了一些方便的RequestMatcher对象,你可以与Spring Security结合使用。

一个典型的Spring Security配置可能如下所示:

import org.springframework.boot.actuate.autoconfigure.security.servlet.EndpointRequest;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.web.SecurityFilterChain;

import static org.springframework.security.config.Customizer.withDefaults;

@Configuration(proxyBeanMethods = false)
public class MySecurityConfiguration {

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http.securityMatcher(EndpointRequest.toAnyEndpoint());
        http.authorizeHttpRequests((requests) -> requests.anyRequest().hasRole("ENDPOINT_ADMIN"));
        http.httpBasic(withDefaults());
        return http.build();
    }

}

前面的示例使用EndpointRequest.toAnyEndpoint()来匹配任何端点的请求,然后确保所有端点都具有ENDPOINT_ADMIN角色。EndpointRequest还提供了其它几个匹配器方法。

如果你将应用程序部署在防火墙后面,你可能希望所有Actuator端点都可以无需身份验证即可访问。你可以通过更改management.endpoints.web.exposure.include属性来实现这一点,如下所示:

management.endpoints.web.exposure.include=*

另外,如果Spring Security存在,你需要添加自定义安全配置,以允许未经身份验证的访问到端点,如下所示:

import org.springframework.boot.actuate.autoconfigure.security.servlet.EndpointRequest;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.web.SecurityFilterChain;

@Configuration(proxyBeanMethods = false)
public class MySecurityConfiguration {

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http.securityMatcher(EndpointRequest.toAnyEndpoint());
        http.authorizeHttpRequests((requests) -> requests.anyRequest().permitAll());
        return http.build();
    }

}

注意:在前面的两个示例中,配置仅适用于Actuator端点。由于Spring Boot的安全配置在存在任何SecurityFilterChain bean时会完全后退,因此你需要配置一个额外的SecurityFilterChain bean,其中包含适用于应用程序其余部分的规则。

跨站请求伪造保护(Cross Site Request Forgery Protection)

由于Spring Boot依赖于Spring Security的默认设置,因此默认情况下会启用CSRF保护。这意味着,当使用默认的安全配置时,需要POST(shutdown和loggers端点)、PUTDELETE的Actuator端点将返回403(禁止)错误。

注意:建议只有在创建由非浏览器客户端使用的服务时才完全禁用CSRF保护。

配置端点(Configuring Endpoints)

端点会自动缓存不带任何参数的读取操作的响应。要配置端点缓存响应的时间,请使用其cache.time-to-live属性。以下示例将beans端点的缓存存活时间设置为10秒:

management.endpoint.beans.cache.time-to-live=10s

注意management.endpoint.<name>前缀唯一标识正在配置的端点。

敏感值的净化(Sanitize Sensitive Values)

/env/configprops/quartz 端点返回的信息可能有些敏感。默认情况下,所有值都会被净化(即替换为 ******)。可以为每个端点使用 showValues 属性来配置以未净化的形式查看原始值。此属性可以配置为具有以下值:

  • ALWAYS - 向所有用户显示所有值的未净化形式
  • NEVER - 所有值总是被净化(即替换为 ******)
  • WHEN_AUTHORIZED - 向已授权的用户显示所有值的未净化形式

对于HTTP端点,如果用户已进行身份验证并具有由端点的 roles 属性配置的角色,则视为已授权。默认情况下,任何已身份验证的用户都是已授权的。对于JMX端点,所有用户始终都是已授权的。

management.endpoint.env.show-values=WHEN_AUTHORIZED
management.endpoint.env.roles=admin

上面的配置启用了具有admin角色的所有用户从/env端点以原始形式查看所有值的功能。

注意:当show-values设置为ALWAYSWHEN_AUTHORIZED时,仍会应用由SanitizingFunction应用的任何清理。

Actuator Web端点的超媒体

将添加一个“discovery page”,其中包含指向所有端点的链接。默认情况下,“discovery page”位于/actuator上。

要禁用“discovery page”,请将以下属性添加到你的应用程序属性中:

management.endpoints.web.discovery.enabled=false

当配置了自定义的管理上下文路径时,“discovery page”会自动从/actuator移动到管理上下文的根目录。例如,如果管理上下文路径是/management,则可以从/management访问discovery page。当管理上下文路径设置为/时,禁用发现页面以防止与其它映射发生冲突的可能性。

CORS支持

跨源资源共享(CORS)是一项W3C规范,允许以灵活的方式指定哪些跨域请求被授权。如果使用Spring MVC或Spring WebFlux,则可以配置Actuator的Web端点以支持此类场景。

默认情况下,CORS支持被禁用,只有设置了management.endpoints.web.cors.allowed-origins属性后才会启用。以下配置允许来自example.com域的GET和POST调用:

management.endpoints.web.cors.allowed-origins=https://example.com
management.endpoints.web.cors.allowed-methods=GET,POST

实现自定义端点

如果你添加了一个用@Endpoint注解的@Bean,那么任何用@ReadOperation@WriteOperation@DeleteOperation注解的方法都会自动通过JMX暴露,并且在一个Web应用程序中,也会通过HTTP暴露。端点可以通过Jersey、Spring MVC或Spring WebFlux在HTTP上暴露。如果Jersey和Spring MVC都可用,则使用Spring MVC。

以下示例展示了一个返回自定义对象的读取操作:

@ReadOperation
public CustomData getData() {
    return new CustomData("test", 5);
}

还可以使用@JmxEndpoint@WebEndpoint编写特定于技术的端点。这些端点仅限于它们各自的技术。例如,@WebEndpoint仅通过HTTP暴露,而不通过JMX暴露。

可以使用@EndpointWebExtension@EndpointJmxExtension编写特定于技术的扩展。这些注解允许提供特定于技术的操作来增强现有端点。

最后,如果需要访问Web框架特定的功能,可以实现servlet或Spring @Controller@RestController端点,但代价是它们不能通过JMX或在使用不同的Web框架时使用。

接收输入

端点上的操作通过其参数接收输入。当通过Web暴露时,这些参数的值取自URL的查询参数和JSON请求体。当通过JMX暴露时,参数将映射到MBean操作的参数。默认情况下,参数是必需的。可以通过使用@javax.annotation.Nullable@org.springframework.lang.Nullable对它们进行注解来将其设置为可选。

可以将JSON请求体中的每个根属性映射到端点的一个参数。考虑以下JSON请求体:

{
    "name": "test",
    "counter": 42
}

可以使用它来调用采用String nameint counter参数的写操作,如下例所示:

@WriteOperation
public void updateData(String name, int counter) {
    // injects "test" and 42
}

提示:由于端点与技术无关,因此在方法签名中只能指定简单类型。特别是,不支持声明一个具有定义名称和计数器属性的CustomData类型的单个参数。

注意:为了让输入映射到操作方法的参数,实现端点的Java代码应该使用-parameters进行编译,而实现端点的Kotlin代码应该使用-java-parameters进行编译。如果使用Spring Boot的Gradle插件,或者使用Maven和spring-boot-starter-parent,那么这会自动发生。

输入类型转换

传递给端点操作方法的参数(如果需要)会自动转换为所需类型。在调用操作方法之前,通过JMX或HTTP接收到的输入将使用ApplicationConversionService的实例以及使用@EndpointConverter 修饰的任何ConverterGenericConverter bean转换为所需类型。

自定义Web端点

对于@Endpoint@WebEndpoint@EndpointWebExtension上的操作,将使用Jersey、Spring MVC或Spring WebFlux自动通过HTTP进行暴露。如果Jersey和Spring MVC都可用,则将使用Spring MVC。

Web端点请求谓词(Web Endpoint Request Predicates)

对于每个通过Web公开的端点上的操作,都会自动生成一个请求谓词。

请求谓词(Request Predicates)是用于匹配传入的HTTP请求的条件或规则。在Spring WebFlux或Spring MVC中,这些谓词可以帮助确定哪些请求应该被路由到特定的处理器方法或端点操作。对于通过@WebEndpoint暴露的每个操作,框架会自动生成一个与该操作的参数和路径相对应的请求谓词。

路径

谓词的路径由端点的ID和Web公开端点的基本路径决定。默认的基本路径是/actuator。例如,ID为sessions的端点在谓词中的路径为/actuator/sessions

可以通过将操作方法的一个或多个参数注解为@Selector来进一步自定义路径。这样的参数作为路径变量添加到路径谓词中。当调用端点操作时,变量的值将传递给操作方法。如果想捕获所有剩余的路径元素,可以将@Selector(Match=ALL_REMAINING)添加到最后一个参数,并将其类型设置为与String[]兼容的类型。

HTTP方法

谓词的HTTP方法由操作类型决定,如下所示:
在这里插入图片描述

消费(Consumes)

对于使用请求体的@WriteOperation(HTTP POST)操作,谓词的消费(consumes)子句是application/vnd.spring-boot.actuator.v2+jsonapplication/json。对于所有其它操作,消费子句为空。

生成(Produces)

谓词的生成类型(produces)子句可以通过@DeleteOperation@ReadOperation@WriteOperation注解的produces属性来确定。该属性是可选的。如果未使用,生成类型子句将自动确定。

如果操作方法返回voidVoid,生成类型子句为空。如果操作方法返回一个org.springframework.core.io.Resource,生成类型子句为application/octet-stream。对于所有其它操作,生成类型子句为application/vnd.spring-boot.actuator.v2+json和application/json

Web端点响应状态

端点操作的默认响应状态取决于操作类型(读取、写入或删除)以及操作返回的内容(如果有的话)。

对于@ReadOperation,如果它返回一个值,则响应状态将为200(OK)。如果它不返回任何值,则响应状态将为404(未找到)。

对于@WriteOperation@DeleteOperation,如果它们返回一个值,则响应状态将为200(OK)。如果它们不返回任何值,则响应状态将为204(无内容)。

如果操作在没有必需参数的情况下被调用,或者参数无法转换为所需类型,则不会调用操作方法,并且响应状态将为400(错误请求)。

Web端点范围请求

可以使用HTTP范围请求来请求HTTP资源的部分内容。当使用Spring MVC或Spring Web Flux时,返回org.springframework.core.io.Resource的操作方法会自动支持范围请求。

注意:在使用Jersey时不支持范围请求。

Web端点安全性

Web端点或特定于Web的端点扩展上的操作可以接收当前的java.security.Principalorg.springframework.boot.actuate.endpoint.SecurityContext作为方法参数。前者通常与@Nullable一起使用,以针对已认证和未认证的用户提供不同的行为。后者通常用于执行授权检查,通过其isUserInRole(String)方法。

Servlet端点

通过实现用@ServletEndpoint注解的类,并且同时实现Supplier<EndpointServlet>接口,可以将Servlet暴露为端点。Servlet端点与Servlet容器提供了更深入的集成,但代价是可移植性降低。它们旨在用于将现有的Servlet暴露为端点。对于新的端点,应尽可能优先使用@Endpoint@WebEndpoint注解。

控制器端点

可以使用@ControllerEndpoint@RestControllerEndpoint注解来实现仅由Spring MVC或Spring WebFlux暴露的端点。这些方法通过Spring MVC和Spring WebFlux的标准注解进行映射,如@RequestMapping@GetMapping,其中端点的ID用作路径的前缀。控制器端点与Spring的Web框架提供了更深入的集成,但代价是可移植性降低。因此,在可能的情况下,应优先使用@Endpoint@WebEndpoint注解。

健康信息

可以使用健康信息来检查正在运行的应用程序的状态。监控软件通常会使用这些信息,以便在生产系统出现故障时发出警报。健康端点所暴露的信息取决于management.endpoint.health.show-detailsmanagement.endpoint.health.show-components这两个属性,这两个属性可以配置为以下值之一:
在这里插入图片描述

默认值是“never”。当用户属于端点的一个或多个角色时,他们被视为已授权。如果端点没有配置角色(这是默认情况),则所有已验证的用户都被视为已授权。可以通过使用management.endpoint.health.roles属性来配置角色。

注意:如果你已经对应用程序进行了安全保护,并希望使用“always”选项,那么你的安全配置必须允许已验证和未验证的用户都能够访问健康端点。

健康信息是从HealthContributorRegistry的内容中收集的(默认情况下,包括在ApplicationContext中定义的所有HealthContributor实例)。Spring Boot包含了许多自动配置的HealthContributor,也可以编写自己的HealthContributor

HealthContributor可以是HealthIndicatorCompositeHealthContributorHealthIndicator提供实际的健康信息,包括一个StatusCompositeHealthContributor则提供其它HealthContributor的组合。这些贡献者共同形成了一个树形结构,以表示整个系统的健康状况。

默认情况下,最终的系统健康状态是由StatusAggregator根据每个HealthIndicator的状态排序得出的。排序列表中的第一个状态被用作整体健康状态。如果没有HealthIndicator返回StatusAggregator已知的状态,那么将使用UNKNOWN状态。

提示:可以在运行时使用HealthContributorRegistry来注册和注销健康指示器。

自动配置的健康指示器

在适当的情况下,Spring Boot会自动配置以下表格中列出的健康指示器。还可以通过配置management.health.key.enabled(其中key为以下表格中列出的键)来启用或禁用选定的指示器:
在这里插入图片描述
在这里插入图片描述

提示:您以通过设置management.health.defaults.enabled属性来全部禁用它们。

还有其它的健康指示器可用,但默认情况下它们不会被启用:
在这里插入图片描述

编写自定义健康指示器

为了提供自定义的健康信息,可以注册实现HealthIndicator接口的Spring bean。你需要提供health()方法的实现,并返回一个Health响应。Health响应应该包含一个状态,并且可以选择性地包含要显示的额外详细信息。以下代码展示了一个示例HealthIndicator实现:

import org.springframework.boot.actuate.health.Health;
import org.springframework.boot.actuate.health.HealthIndicator;
import org.springframework.stereotype.Component;

@Component
public class MyHealthIndicator implements HealthIndicator {

    @Override
    public Health health() {
        int errorCode = check();
        if (errorCode != 0) {
            return Health.down().withDetail("Error Code", errorCode).build();
        }
        return Health.up().build();
    }

    private int check() {
        // perform some specific health check
        return ...
    }

}

注意:对于给定的HealthIndicator,其标识符是bean的名称(如果存在的话),但不包括HealthIndicator后缀。在前面的示例中,健康信息可在名为my的条目中访问。

提示:健康指示器通常通过HTTP调用,并且需要在任何连接超时之前响应。如果健康指示器的响应时间超过10秒,Spring Boot将记录一个警告消息。如果想要配置这个阈值,可以使用management.endpoint.health.logging.slow-indicator-threshold属性。

除了Spring Boot预定义的状态类型外,Health还可以返回一个代表新系统状态的自定义Status 。在这种情况下,还需要提供StatusAggregator接口的自定义实现,或者必须使用management.endpoint.health.status.order配置属性来配置默认实现。

例如,假设在一个HealthIndicator实现中使用了一个新状态,其代码为FATAL。要配置严重性顺序,请在应用程序属性中添加以下属性:

management.endpoint.health.status.order=fatal,down,out-of-service,unknown,up

响应中的HTTP状态码反映了整体健康状况。默认情况下,OUT_OF_SERVICEDOWN映射到503。任何未映射的健康状态,包括UP,都映射到200。如果通过HTTP访问健康端点,可能还想注册自定义状态映射。配置自定义映射将禁用DOWNOUT_OF_SERVICE的默认映射。如果想保留默认映射,则必须明确配置它们,以及任何自定义映射。例如,以下属性将FATAL映射到503(服务不可用),并保留DOWNOUT_OF_SERVICE的默认映射:

management.endpoint.health.status.http-mapping.down=503
management.endpoint.health.status.http-mapping.fatal=503
management.endpoint.health.status.http-mapping.out-of-service=503

提示:如果需要更多的控制权,可以定义自己的HttpCodeStatusMapper bean。

下表显示了内置状态的默认状态映射:
在这里插入图片描述

响应式健康指示器

对于响应式应用程序,如使用Spring WebFlux的应用程序,ReactiveHealthContributor提供了一个非阻塞式的合约来获取应用程序的健康状况。与传统HealthContributor类似,健康信息从ReactiveHealthContributorRegistry的内容中收集(默认情况下,从你在ApplicationContext中定义的所有HealthContributorReactiveHealthContributor实例中收集)。不检查响应式API的常规HealthContributors在弹性调度器上执行。

提示:在一个响应式应用程序中,你应该使用ReactiveHealthContributorRegistry来在运行时注册和注销健康指示器。如果你需要注册一个常规的HealthContributor,你应该使用ReactiveHealthContributor#adapt来将其包装。

为了从响应式 API 提供自定义的健康信息,你可以注册实现了 ReactiveHealthIndicator 接口的 Spring bean。以下代码展示了一个 ReactiveHealthIndicator 的实现示例:

import reactor.core.publisher.Mono;

import org.springframework.boot.actuate.health.Health;
import org.springframework.boot.actuate.health.ReactiveHealthIndicator;
import org.springframework.stereotype.Component;

@Component
public class MyReactiveHealthIndicator implements ReactiveHealthIndicator {

    @Override
    public Mono<Health> health() {
        return doHealthCheck().onErrorResume((exception) ->
            Mono.just(new Health.Builder().down(exception).build()));
    }

    private Mono<Health> doHealthCheck() {
        // perform some specific health check
        return ...
    }

}

提示:为了自动处理错误,可以考虑从AbstractReactiveHealthIndicator类进行扩展。

自动配置的 ReactiveHealthIndicators

在适当的情况下,Spring Boot 会自动配置以下 ReactiveHealthIndicators
在这里插入图片描述

提示:如果必要,响应式指示器会替换常规的指示器。此外,任何没有明确处理的 HealthIndicator 都会自动被包装。

健康组

有时,将健康指示器组织成不同目的的组是有用的。

要创建一个健康指示器组,可以使用management.endpoint.health.group.<name>属性,并指定要includeexclude的健康指示器ID列表。例如,要创建一个仅包含数据库指示器的组,您可以定义以下内容:

management.endpoint.health.group.custom.include=db

之后,你可以通过访问 localhost:8080/actuator/health/custom 来检查结果。

类似地,要创建一个排除数据库指示器并包含所有其它指示器的组,你可以定义如下:

management.endpoint.health.group.custom.exclude=db

默认情况下,如果健康组包含或排除了不存在的健康指示器,启动将失败。要禁用此行为,请将management.endpoint.health.validate-group-membership设置为false

默认情况下,组继承与系统健康相同的StatusAggregatorHttpCodeStatusMapper设置。但是,也可以为每个组单独定义这些设置。如果需要,还可以覆盖show-detailsroles属性:

management.endpoint.health.group.custom.show-details=when-authorized
management.endpoint.health.group.custom.roles=admin
management.endpoint.health.group.custom.status.order=fatal,up
management.endpoint.health.group.custom.status.http-mapping.fatal=500
management.endpoint.health.group.custom.status.http-mapping.out-of-service=500

提示:如果你需要为组注册自定义的 StatusAggregatorHttpCodeStatusMapper beans,你可以使用 @Qualifier("groupname") 注解。

健康组还可以包含/排除 CompositeHealthContributor。还可以仅包含/排除 CompositeHealthContributor 的某个特定组件。这可以通过使用组件的完全限定名来完成,如下所示:

management.endpoint.health.group.custom.include="test/primary"
management.endpoint.health.group.custom.exclude="test/primary/b"

在上面的例子中,自定义组将包括名为 primaryHealthContributor,它是复合组件 test 的一部分。这里,primary 本身也是一个复合组件,名为 bHealthContributor 将从自定义组中排除。

健康组可以在主端口或管理端口上的额外路径上提供。这在云环境(如 Kubernetes)中非常有用,因为在这些环境中出于安全考虑,经常使用单独的管理端口为 actuator 端点提供服务。使用单独的端口可能会导致不可靠的健康检查,因为即使健康检查成功,主应用程序也可能无法正常工作。可以通过以下方式配置健康组的额外路径:

management.endpoint.health.group.live.additional-path="server:/healthz"

这将使名为“live”的健康组在主服务器端口的 /healthz 路径上可用。前缀是必需的,必须是 server:(代表主服务器端口)或 management:(如果已配置,则代表管理端口)。路径必须是单个路径段。

DataSource 健康

DataSource 健康指示器可以显示标准数据源和路由数据源 bean 的健康状况。路由数据源的健康状况包括其每个目标数据源的健康状况。在健康端点的响应中,每个路由数据源的目标都会通过其路由键来命名。如果你不希望将路由数据源包含在指示器的输出中,请将 management.health.db.ignore-routing-data-sources 设置为 true

Kubernetes Probes(探测)

部署在 Kubernetes 上的应用程序可以使用容器探测来提供有关其内部状态的信息。根据你的 Kubernetes 配置,kubelet 会调用这些探测并根据结果做出反应。

默认情况下,Spring Boot 管理你的应用程序可用性状态。如果部署在 Kubernetes 环境中,actuator 会从 ApplicationAvailability 接口收集“活动”(Liveness)和“就绪”(Readiness)信息,并在专门的健康指标中:LivenessStateHealthIndicatorReadinessStateHealthIndicator 使用这些信息。这些指标显示在全局健康端点(“/actuator/health”)上。它们还通过健康组作为单独的 HTTP 探测暴露出来:“/actuator/health/liveness” 和 “/actuator/health/readiness”。

然后,你可以使用以下端点信息配置你的 Kubernetes 基础设施:

livenessProbe:
  httpGet:
    path: "/actuator/health/liveness"
    port: <actuator-port>
  failureThreshold: ...
  periodSeconds: ...

readinessProbe:
  httpGet:
    path: "/actuator/health/readiness"
    port: <actuator-port>
  failureThreshold: ...
  periodSeconds: ...

注意<actuator-port> 应该设置为 actuator 端点可用的端口。这可能是主 Web 服务器端口,或者如果设置了 “management.server.port” 属性,则可能是单独的管理端口。

这些健康组仅在应用程序运行在 Kubernetes 环境中时自动启用。可以通过使用 management.endpoint.health.probes.enabled 配置属性在任何环境中启用它们。

注意:如果应用程序的启动时间超过了配置的活动周期,Kubernetes 会提到 “startupProbe”作为可能的解决方案。通常来说,这里并不一定需要“startupProbe”,因为“readinessProbe”会在所有启动任务完成之前失败。这意味着你的应用程序在准备就绪之前不会接收到流量。然而,如果你的应用程序需要花费很长时间来启动,请考虑使用“startupProbe”来确保 Kubernetes 在应用程序启动过程中不会杀死它。

如果你的 Actuator 端点部署在单独的管理上下文中,那么这些端点不会使用与主应用程序相同的 Web 基础设施(端口、连接池、框架组件)。在这种情况下,即使主应用程序没有正常工作(例如,无法接受新的连接),探测检查也可能成功。因此,将LivenessReadiness健康组暴露在主服务器端口上是一个好主意。这可以通过设置以下属性来实现:

management.endpoint.health.probes.add-additional-paths=true

这将使得活动(liveness)组在主服务器端口上的 /livez 路径下可用,同时使得就绪(readiness)组在 /readyz 路径下可用。可以通过在每个组上使用 additional-path 属性来自定义路径。

使用 Kubernetes 探测检查外部状态

Actuator 将“liveness”和“readiness”探针配置为健康组(Health Groups)。这意味着所有健康组的功能都可用于它们。例如,可以配置额外的健康指标(Health Indicators):

management.endpoint.health.group.readiness.include=readinessState,customCheck

默认情况下,Spring Boot 不会向这些组中添加其它健康指标器。

“活动”(liveness)探针不应依赖于外部系统的健康检查。如果应用程序的活动状态被破坏,Kubernetes 会尝试通过重启应用程序实例来解决该问题。这意味着,如果外部系统(如数据库、Web API 或外部缓存)出现故障,Kubernetes 可能会重启所有应用程序实例并引发级联故障。

至于“就绪”(readiness)探针,检查外部系统的选择必须由应用程序开发人员谨慎进行。因此,Spring Boot 在就绪探针中不包含任何额外的健康检查。如果应用程序实例的就绪状态未就绪,Kubernetes 不会将流量路由到该实例。某些外部系统可能不是由应用程序实例共享的,在这种情况下,它们可以包含在就绪探针中。其它外部系统可能对应用程序不是必需的(应用程序可能具有断路器和备用方案),在这种情况下,它们绝对不应包含在内。遗憾的是,所有应用程序实例共享一个外部系统是很常见的,你必须做出判断:将其包含在就绪探针中,并期望当外部服务出现故障时应用程序能够停止服务;或者将其排除在外,并在堆栈的更高级别处理故障,可能通过在调用方中使用断路器来实现。

注意:如果一个应用程序的所有实例都处于未就绪状态,那么类型为 type=ClusterIPNodePort 的 Kubernetes Service 将不接受任何传入连接。由于没有连接,因此不会返回 HTTP 错误响应(例如 503)。对于类型为 type=LoadBalancer 的服务,是否接受连接取决于提供者。具有显式入口的服务(ingress)的响应方式也取决于其实现——入口服务本身必须决定如何处理来自下游的“连接被拒绝”。对于负载均衡器和入口服务,返回 HTTP 503 的可能性都很大。

此外,如果应用程序使用 Kubernetes 自动扩展功能,则根据其自动扩展器配置,应用程序可能会对从负载均衡器中删除的应用程序做出不同的反应。

应用程序生命周期和探测状态

Kubernetes 探测支持的一个重要方面是它与应用程序生命周期的一致性。可用状态(AvailabilityState,即应用程序的内存内部状态)和实际探测(暴露该状态)之间存在显著差异。根据应用程序生命周期的不同阶段,探测可能不可用。

Spring Boot 在启动和关闭过程中发布应用程序事件,探测可以监听这些事件并暴露可用状态(AvailabilityState )信息。

下表显示了不同阶段下AvailabilityState和 HTTP 连接器的状态。

当 Spring Boot 应用程序启动时:
在这里插入图片描述

当 Spring Boot 应用程序关闭时:
在这里插入图片描述

应用程序信息

应用程序信息会公开从 ApplicationContext 中定义的所有 InfoContributor bean 收集的各种信息。Spring Boot 包含许多自动配置的 InfoContributor bean,你也可以编写自己的 bean。

自动配置的 InfoContributor

在适当的情况下,Spring 会自动配置以下 InfoContributor bean:
在这里插入图片描述

单个贡献者是否启用由 management.info.<id>.enabled 属性控制。不同的贡献者根据它们的前提条件和所公开信息的性质,对这个属性有不同的默认值。

由于没有任何前提条件表明它们应该被启用,因此 envjavaos 贡献者默认情况下是禁用的。每个贡献者都可以通过将其 management.info.<id>.enabled 属性设置为 true 来启用。

buildgit info 贡献者默认是启用的。每个贡献者都可以通过将其 management.info.<id>.enabled 属性设置为 false 来禁用。或者,要禁用通常默认情况下启用的每个贡献者,请将 management.info.defaults.enabled 属性设置为 false

自定义应用程序信息

env 贡献者启用时,可以通过设置 info.* Spring 属性来自定义 info 端点公开的数据。info 键下的所有 Environment 属性都会自动公开。例如,可以在 application.properties 文件中添加以下设置:

info.app.encoding=UTF-8
info.app.java.source=17
info.app.java.target=17

提示
不是硬编码这些值,还可以在构建时扩展 info 属性。

假设使用 Maven,可以将前面的示例重写为:

info.app.encoding=@project.build.sourceEncoding@
info.app.java.source=@java.version@
info.app.java.target=@java.version@

Git 提交信息

info 端点的另一个有用功能是,它能够在项目构建时发布有关 Git 源代码仓库状态的信息。如果 GitProperties bean 可用,你可以使用 info 端点来公开这些属性。

提示:如果类路径的根目录下有 git.properties 文件,则会自动配置 GitProperties bean。

默认情况下,如果可用,该端点将公开 git.branchgit.commit.idgit.commit.time 属性。如果不希望这些属性出现在端点响应中,则需要从 git.properties 文件中排除它们。如果想显示完整的 git 信息(即 git.properties 的完整内容),请使用以下 management.info.git.mode 属性:

management.info.git.mode=full

要完全从 info 端点禁用 git 提交信息,请将 management.info.git.enabled 属性设置为 false,如下所示:

management.info.git.enabled=false

构建信息

如果BuildProperties bean 可用 ,则 info 端点还可以发布有关构建的信息。如果类路径中存在 META-INF/build-info.properties 文件,则会发生这种情况。

提示:Maven 和 Gradle 插件都可以生成该文件。

Java 信息

info 端点会发布有关 Java 运行时环境的信息。

操作系统信息

info 端点会发布有关操作系统的信息。

编写自定义的 InfoContributor

要提供自定义的应用程序信息,可以注册实现 InfoContributor 接口的 Spring bean。

以下示例贡献了一个具有单个值的example 示例条目:

import java.util.Collections;

import org.springframework.boot.actuate.info.Info;
import org.springframework.boot.actuate.info.InfoContributor;
import org.springframework.stereotype.Component;

@Component
public class MyInfoContributor implements InfoContributor {

    @Override
    public void contribute(Info.Builder builder) {
        builder.withDetail("example", Collections.singletonMap("key", "value"));
    }

}

如果你访问 info 端点,应该看到包含以下附加条目的响应:

{
    "example": {
        "key" : "value"
    }
}
  • 15
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值