20220524 Production-ready Features
前言
Spring Boot 包含许多其他功能,可帮助您在将应用程序推送到生产环境时对其进行监控和管理。您可以选择使用 HTTP 端点或 JMX 管理和监视您的应用程序。审计(auditing),健康状况(health)和指标收集(metrics gathering)也可以自动应用于您的应用程序。
1. 启用生产就绪功能(Production-ready Features)
spring-boot-actuator
模块提供了 Spring Boot 的所有生产就绪功能。启用功能的最简单方法是添加依赖项,spring-boot-starter-actuator
启动器。
执行器的定义:
执行器是制造术语,是指用于移动或控制某些物体的机械设备。执行器可以通过很小的变化产生大量的动作。
要将执行器添加到基于 Maven 的项目中,请添加以下依赖项:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
</dependencies>
对于 Gradle
,请使用以下声明:
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-actuator'
}
2. 端点(Endpoints)
执行器端点使您可以监视应用程序并与之交互。Spring Boot 包含许多内置端点,并允许您添加自己的端点。例如,health
端点提供基本的应用程序健康信息。
您可以 启用或禁用 每个单独的端点以及 通过 HTTP 或 JMX 公开它们(使它们可以远程访问) 。当端点被启用和公开时,它被认为是可用的。内置端点仅在可用时才会自动配置。大多数应用程序选择通过 HTTP 公开,其中端点的 ID 和前缀 /actuator
映射到 URL 。例如,默认情况下,health
端点映射到 /actuator/health
以下与技术无关的端点可用:
ID | 描述 |
---|---|
auditevents |
公开当前应用程序的审计事件信息。需要一个 AuditEventRepository bean |
beans |
显示应用程序中所有 Spring beans 的完整列表 |
caches |
公开可用的缓存 |
conditions |
显示在配置和自动配置类上评估的条件以及它们匹配或不匹配的原因 |
configprops |
显示所有 @ConfigurationProperties 的整理列表(collated list) |
env |
公开 Spring ConfigurableEnvironment 的属性 |
flyway |
显示任何已应用的 Flyway 数据库迁移。需要一个或多个 Flyway beans |
health |
显示应用程序运行状况信息 |
httptrace |
显示 HTTP 跟踪信息(默认情况下,最近 100 个 HTTP 请求-响应交换)。需要一个 HttpTraceRepository bean |
info |
显示任意应用程序信息 |
integrationgraph |
显示 Spring Integration 图。需要依赖项 spring-integration-core |
loggers |
显示和修改应用程序中记录器的配置 |
liquibase |
显示已应用的所有 Liquibase 数据库迁移。需要一个或多个 Liquibase bean |
metrics |
显示当前应用程序的 “指标”(metrics) 信息 |
mappings |
显示所有 @RequestMapping 路径的整理列表 |
quartz |
显示有关 Quartz Scheduler 作业的信息 |
scheduledtasks |
显示应用程序中的计划任务 |
sessions |
允许从 Spring Session 支持的会话存储中检索和删除用户会话。需要使用 Spring Session 的基于 servlet 的 Web 应用程序 |
shutdown |
让应用程序正常关闭。默认禁用。 |
startup |
显示 ApplicationStartup 收集的 启动步骤数据 。要求将 SpringApplication 配置为 BufferingApplicationStartup |
threaddump |
执行线程转储 |
如果您的应用程序是 Web 应用程序(Spring MVC ,Spring WebFlux 或 Jersey),则可以使用以下额外的端点:
ID | 描述 |
---|---|
heapdump |
返回堆转储文件。在 HotSpot JVM 上,返回一个 HPROF 格式文件。在 OpenJ9 JVM 上,返回一个 PHD 格式文件 |
jolokia |
当 Jolokia 在类路径上时,通过 HTTP 公开 JMX bean(不适用于 WebFlux)。需要依赖 jolokia-core |
logfile |
返回日志文件的内容(如果已设置 logging.file.name 或 logging.file.path 属性)。支持使用 HTTP Range 标头来检索部分日志文件的内容 |
prometheus |
以 Prometheus 服务器可以抓取的格式公开指标。需要依赖 micrometer-registry-prometheus |
2.1. 启用端点
默认情况下,所有端点除 shutdown
外均处于启用状态。要配置端点的启用,请使用 management.endpoint.<id>.enabled
属性。以下示例启用 shutdown
端点:
management.endpoint.shutdown.enabled=true
如果您希望端点启用是选择加入而不是选择退出,请将 management.endpoints.enabled-by-default
属性设置为 false
,并设置各个端点 enabled
属性重新启用。以下示例启用 info
端点并禁用所有其他端点:
management.endpoints.enabled-by-default=false
management.endpoint.info.enabled=true
禁用的端点将从应用上下文中完全删除。如果只想更改公开端点的技术,请使用
include
和exclude
属性
2.2. 公开端点
由于端点可能包含敏感信息,您应该仔细考虑何时公开它们。下表显示了内置端点的默认公开:
ID | JMX | Web |
---|---|---|
auditevents |
Yes | No |
beans |
Yes | No |
caches |
Yes | No |
conditions |
Yes | No |
configprops |
Yes | No |
env |
Yes | No |
flyway |
Yes | No |
health |
Yes | Yes |
heapdump |
N/A | No |
httptrace |
Yes | No |
info |
Yes | No |
integrationgraph |
Yes | No |
jolokia |
N/A | No |
logfile |
N/A | No |
loggers |
Yes | No |
liquibase |
Yes | No |
metrics |
Yes | No |
mappings |
Yes | No |
prometheus |
N/A | No |
quartz |
Yes | No |
scheduledtasks |
Yes | No |
sessions |
Yes | No |
shutdown |
Yes | No |
startup |
Yes | No |
threaddump |
Yes | No |
要更改公开的端点,请使用以下技术特定的 include
和 exclude
属性:
Property | Default |
---|---|
management.endpoints.jmx.exposure.exclude |
|
management.endpoints.jmx.exposure.include |
* |
management.endpoints.web.exposure.exclude |
|
management.endpoints.web.exposure.include |
health |
include
属性列出了公开的端点的 ID 。exclude
属性列出不应公开的端点的 ID 。exclude
属性优先于 include
属性。您可以使用端点 ID 列表来配置 include
和 exclude
属性。
例如,要停止通过 JMX 公开所有端点并仅公开 health
和 info
端点,请使用以下属性:
management.endpoints.jmx.exposure.include=health,info
*
可用于选择所有端点。例如,要通过 HTTP 公开除 env
和 beans
端点之外的所有内容,请使用以下属性:
management.endpoints.web.exposure.include=*
management.endpoints.web.exposure.exclude=env,beans
*
在 YAML 中具有特殊含义,因此如果要包含(或排除)所有端点,请务必添加引号
如果您的应用程序是公开的,我们强烈建议您 保护您的端点
如果您想在端点公开时实现自己的策略,您可以注册一个
EndpointFilter
bean
2.3. Security
出于安全目的,默认情况下只有 /health
端点通过 HTTP 公开。您可以使用 management.endpoints.web.exposure.include
属性来配置公开的端点。
在设置
management.endpoints.web.exposure.include
之前,请确保公开的执行器不包含敏感信息,通过将它们放在防火墙后面来保护它们,或者通过 Spring Security 之类的东西来保护它们。
如果 Spring Security 在 classpath 上并且没有其他 WebSecurityConfigurerAdapter
或 SecurityFilterChain
bean 存在,则除 /health
之外的所有执行器都受到 Spring Boot 自动配置保护。如果您定义了自定义 WebSecurityConfigurerAdapter
或 SecurityFilterChain
bean ,Spring Boot 自动配置会退出并让您完全控制执行器访问规则。
如果您希望为 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;
@Configuration(proxyBeanMethods = false)
public class MySecurityConfiguration {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http.requestMatcher(EndpointRequest.toAnyEndpoint())
.authorizeRequests((requests) -> requests.anyRequest().hasRole("ENDPOINT_ADMIN"));
http.httpBasic();
return http.build();
}
}
前面的示例使用 EndpointRequest.toAnyEndpoint()
将请求匹配到任何端点,然后确保所有端点都具有 ENDPOINT_ADMIN
角色。其他几种匹配器方法也可以在 EndpointRequest
上可用。有关详细信息,请参阅 API 文档( HTML 或 PDF )。
如果您在防火墙后面部署应用程序,您可能希望无需身份验证即可访问所有执行器端点。您可以通过更改 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.requestMatcher(EndpointRequest.toAnyEndpoint())
.authorizeRequests((requests) -> requests.anyRequest().permitAll());
return http.build();
}
}
在前面的两个示例中,配置仅适用于执行器端点。由于 Spring Boot 的安全配置在任何
SecurityFilterChain
bean 存在的情况下都会完全退出,因此您需要配置一个额外的SecurityFilterChain
bean ,其规则适用于应用程序的其余部分。
2.3.1. 跨站点请求伪造保护
由于 Spring Boot 依赖于 Spring Security 的默认设置,因此默认开启 CSRF 保护。这意味着在使用默认安全配置时,需要 POST
(关闭和记录器端点)、PUT
或 DELETE
的执行器端点会收到 403(forbidden)错误。
我们建议仅在创建非浏览器客户端使用的服务时完全禁用 CSRF 保护。
您可以在 Spring Security Reference Guide 中找到有关 CSRF 保护的更多信息。
2.4. 配置端点
端点会自动缓存对不带任何参数的读取操作的响应。要配置端点缓存响应的时间量,请使用 cache.time-to-live
属性。以下示例将 beans
端点缓存的生存时间设置为 10 秒:
management.endpoint.beans.cache.time-to-live=10s
management.endpoint.<name>
前缀唯一标识正在配置的端点 。
2.5. Hypermedia for Actuator Web Endpoints
添加了一个“发现页面”,其中包含指向所有端点的链接。默认情况下,“发现页面” /actuator
可用。
要禁用“发现页面”,请将以下属性添加到您的应用程序属性中:
management.endpoints.web.discovery.enabled=false
配置自定义管理上下文路径后,“发现页面”会自动从 /actuator
移动到管理上下文的根目录。例如,如果管理上下文路径是 /management
,那么发现页面可以从 /management
获得。当管理上下文路径设置为 /
时,发现页面被禁用以防止与其他映射发生冲突的可能性。
2.6. 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
有关选项的完整列表,请参阅
CorsEndpointProperties
2.7. 实现自定义端点
如果您添加带有 @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 框架访问。
2.7.1. 接收输入
端点上的操作通过其参数接收输入。当通过 Web 公开时,这些参数的值取自 URL 的查询参数和 JSON 请求正文。通过 JMX 公开时,参数将映射到 MBean 操作的参数。默认情况下需要参数。可以通过使用 @javax.annotation.Nullable
或 @org.springframework.lang.Nullable
注解来使它们成为可选的。
您可以将 JSON 请求正文中的每个根属性映射到端点的参数。考虑以下 JSON 请求正文:
{
"name": "test",
"counter": 42
}
您可以使用它来调用接受 String name
和 int counter
参数的写入操作,如以下示例所示:
@WriteOperation
public void updateData(String name, int counter) {
// injects "test" and 42
}
因为端点与技术无关,所以只能在方法签名中指定简单类型。特别是,不支持使用定义
name
和counter
属性的CustomData
类型声明单个参数。
为了让输入映射到操作方法的参数,实现端点的 Java 代码应该用
-parameters
编译,实现端点的 Kotlin 代码应该用-java-parameters
编译。如果您使用 Spring Boot 的 Gradle 插件或使用 Maven 和spring-boot-starter-parent
,这将自动发生
输入类型转换
如果需要,传递给端点操作方法的参数将自动转换为所需的类型。在调用操作方法之前,通过 JMX 或 HTTP 接收的输入通过使用 ApplicationConversionService
实例以及任何带有 @EndpointConverter
限定的 Converter
或 GenericConverter
bean 转换为所需的类型。
2.7.2. 自定义 Web 端点
使用 Jersey、Spring MVC 或 Spring WebFlux 通过 HTTP 自动公开 @Endpoint
、@WebEndpoint
或 @EndpointWebExtension
上的操作。如果 Jersey 和 Spring MVC 都可用,则使用 Spring MVC 。
Web 端点请求断言(Predicate)
为 Web 公开端点上的每个操作自动生成请求断言。
Path
断言的路径由端点的 ID 和 Web 公开的端点的基本路径确定。默认基本路径是 /actuator
。例如,ID 为 sessions
的端点在断言中用 /actuator/sessions
作其路径。
您可以通过使用 @Selector
注解操作方法的一个或多个参数来进一步自定义路径。这样的参数作为路径变量添加到路径断言中。当调用端点操作时,变量的值被传递到操作方法中。如果要捕获所有剩余的路径元素,可以添加 @Selector(Match=ALL_REMAINING)
到最后一个参数并使其成为与 String[]
转换兼容的类型。
HTTP method
断言的 HTTP 方法由操作类型决定,如下表所示:
Operation | HTTP method |
---|---|
@ReadOperation |
GET |
@WriteOperation |
POST |
@DeleteOperation |
DELETE |
Consumes
对于使用请求体的 @WriteOperation
(HTTP POST
) ,断言的 consume
子句是 application/vnd.spring-boot.actuator.v2+json, application/json
,对于所有其他操作,consumes
子句为空。
Produces
断言的 produces
子句可以由 @DeleteOperation
、@ReadOperation
和 @WriteOperation
注解的 produces
属性确定。属性是可选的。如果未使用,则自动确定 produces
子句。
如果操作方法返回 void
或 Void
,则 produces
子句为空。如果操作方法返回一个 org.springframework.core.io.Resource
,produces
的子句是 application/octet-stream
。对于所有其他操作,produces
子句是 application/vnd.spring-boot.actuator.v2+json, application/json
Web Endpoint Response Status
端点操作的默认响应状态取决于操作类型(读取、写入或删除)以及操作返回的内容(如果有)。
如果 @ReadOperation
返回一个值,则响应状态将为 200(OK)。如果它没有返回值,则响应状态将为 404(未找到)。
如果 @WriteOperation
或 @DeleteOperation
返回值,则响应状态将为 200(OK)。如果它没有返回值,则响应状态将为 204(无内容)。
如果调用操作时不带必填参数或带有无法转换为所需类型的参数,则不会调用操作方法,响应状态为 400(Bad Request)。
Web Endpoint Range Requests
您可以使用 HTTP range 请求来请求 HTTP 资源的一部分。使用 Spring MVC 或 Spring Web Flux 时,返回 org.springframework.core.io.Resource
自动支持范围请求的操作。
使用 Jersey 时不支持范围请求。
Web Endpoint Security
Web 端点或特定于 Web 的端点扩展上的操作可以接收当前 java.security.Principal
或 org.springframework.boot.actuate.endpoint.SecurityContext
作为方法参数。前者通常与 @Nullable
结合使用,为经过身份验证和未经身份验证的用户提供不同的行为。后者通常用于通过使用其 isUserInRole(String)
方法执行授权检查。
2.7.3. Servlet 端点
通过实现一个带有 @ServletEndpoint
注解的类,也实现了 Supplier<EndpointServlet>
,servlet 可以作为端点公开。Servlet 端点提供与 servlet 容器的更深层次的集成,但以牺牲可移植性为代价。它们旨在用于将现有 servlet 公开为端点。对于新端点,应尽可能首选 @Endpoint
和 @WebEndpoint
注解。
2.7.4. Controller Endpoints
您可以使用 @ControllerEndpoint
和 @RestControllerEndpoint
来实现只由 Spring MVC 或 Spring WebFlux 公开的端点。方法通过使用 Spring MVC 和 Spring WebFlux 的标准注解 (如 @RequestMapping
和 @GetMapping
) 进行映射,并使用端点的 ID 作为路径的前缀。控制器端点提供了与 Spring 的 web 框架的更深层次的集成,但代价是可移植性。只要有可能,应尽可能首选 @Endpoint
和 @WebEndpoint
注解。
2.8. Health Information
您可以使用健康信息来检查正在运行的应用程序的状态。当生产系统出现故障时,监控软件经常使用它来提醒某人。health
端点公开的信息取决于 management.endpoint.health.show-details
和 management.endpoint.health.show-components
属性,可以使用以下值之一进行配置:
姓名 | 描述 |
---|---|
never |
从不显示细节 |
when-authorized |
详细信息仅向授权用户显示。可以使用 management.endpoint.health.roles 配置授权角色 |
always |
向所有用户显示详细信息 |
默认值为 never
。当用户处于一个或多个端点角色时,他们被认为是被授权的。如果端点没有配置角色(默认),则所有经过身份验证的用户都被认为是授权的。您可以使用 management.endpoint.health.roles
属性来配置角色。
如果您已保护应用程序并希望使用
always
,则您的安全配置必须允许经过身份验证和未经身份验证的用户访问health
端点
健康信息是从 HealthContributorRegistry
的内容中收集的(默认情况下,您的 ApplicationContext
中定义的所有 HealthContributor
实例)。Spring Boot 包含了一些自动配置的 HealthContributors
,你也可以自己编写。
HealthContributor
可以是 HealthIndicator
或 CompositeHealthContributor
。HealthIndicator
提供实际的健康信息,包括Status
。 CompositeHealthContributor
提供了其他 HealthContributors
的组合。总之,贡献者形成了一个树结构来表示整个系统的健康状况。
默认情况下,最终系统运行状况由 StatusAggregator
派生,它根据状态的有序列表对每个状态进行排序。HealthIndicator
排序列表中的第一个状态用作整体健康状态。如果没有 HealthIndicator
返回 StatusAggregator
已知的状态,则使用 UNKNOWN
状态。
您可以使用
HealthContributorRegistry
来在运行时注册和取消注册健康指标。
2.8.1. 自动配置的 HealthIndicator
在适当的时候,Spring Boot 会自动配置下表中列出的 HealthIndicators
。您也可以通过配置 management.health.key.enabled
启用或禁用选定的指标,使用下表中的 key
:
Key | Name | 描述 |
---|---|---|
cassandra |
CassandraDriverHealthIndicator |
检查 Cassandra 数据库是否已启动 |
couchbase |
CouchbaseHealthIndicator |
检查 Couchbase 集群是否已启动 |
db |
DataSourceHealthIndicator |
检查是否可以获得 DataSource 连接 |
diskspace |
DiskSpaceHealthIndicator |
检查是否磁盘空间不足 |
elasticsearch |
ElasticsearchRestHealthIndicator |
检查 Elasticsearch 集群是否已启动 |
hazelcast |
HazelcastHealthIndicator |
检查 Hazelcast 服务器是否已启动 |
influxdb |
InfluxDbHealthIndicator |
检查 InfluxDB 服务器是否已启动 |
jms |
JmsHealthIndicator |
检查 JMS 代理是否已启动 |
ldap |
LdapHealthIndicator |
检查 LDAP 服务器是否已启动 |
mail |
MailHealthIndicator |
检查邮件服务器是否已启动 |
mongo |
MongoHealthIndicator |
检查 Mongo 数据库是否已启动 |
neo4j |
Neo4jHealthIndicator |
检查 Neo4j 数据库是否已启动 |
ping |
PingHealthIndicator |
始终以 UP 响应 |
rabbit |
RabbitHealthIndicator |
检查 Rabbit 服务器是否已启动 |
redis |
RedisHealthIndicator |
检查 Redis 服务器是否已启动 |
solr |
SolrHealthIndicator |
检查 Solr 服务器是否已启动 |
您可以通过设置
management.health.defaults.enabled
属性来禁用它们
其他 HealthIndicators
可用但默认情况下未启用:
Key | Name | 描述 |
---|---|---|
livenessstate |
LivenessStateHealthIndicator |
公开 Liveness 应用程序可用性状态 |
readinessstate |
ReadinessStateHealthIndicator |
公开 Readiness 应用程序可用性状态 |
2.8.2. 编写自定义 HealthIndicator
要提供自定义健康信息,您可以注册实现 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
的标识符是不带HealthIndicator
后缀的 bean 的名称(如果存在)。在前面的示例中,健康信息位于名为my
的条目中
除了 Spring Boot 的预定义 Status
类型之外,Health
还可以返回一个表示新系统状态的自定义 Status
。在这种情况下,您还需要提供 StatusAggregator
接口的自定义实现,或者您必须使用 management.endpoint.health.status.order
配置属性配置默认实现。
例如,假设在您的一个 HealthIndicator
实现中使用了编码为 FATAL
的新 Status
。要配置严重性顺序,请将以下属性添加到您的应用程序属性中:
management.endpoint.health.status.order=fatal,down,out-of-service,unknown,up
响应中的 HTTP 状态代码反映了整体健康状况。默认情况下,OUT_OF_SERVICE
和 DOWN
映射到 503。任何未映射的健康状态,包括 UP
,都映射到 200 。如果您通过 HTTP 访问健康端点,您可能还需要注册自定义状态映射。配置自定义映射会禁用 DOWN
和 OUT_OF_SERVICE
的默认映射。如果要保留默认映射,则必须显式配置它们以及任何自定义映射。例如,以下属性映射 FATAL
到 503(服务不可用)并保留 DOWN
和 OUT_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
下表显示了内置状态的默认状态映射:
Status | Mapping |
---|---|
DOWN |
SERVICE_UNAVAILABLE ( 503 ) |
OUT_OF_SERVICE |
SERVICE_UNAVAILABLE ( 503 ) |
UP |
默认没有映射,所以 HTTP 状态是 200 |
UNKNOWN |
默认没有映射,所以 HTTP 状态是 200 |
2.8.3. 反应式健康指标
对于响应式应用程序,例如使用 Spring WebFlux 的应用程序,ReactiveHealthContributor
提供了一个非阻塞契约来获取应用程序健康。与传统的 HealthContributor
类似,健康信息是从 ReactiveHealthContributorRegistry
的内容中收集的(默认情况下, 您的 ApplicationContext
中定义的所有 HealthContributor
和 ReactiveHealthContributor
实例)。常规 HealthContributors
不检查响应式 API 在 elastic scheduler 上的执行。
在反应式应用程序中,您应该使用
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
继承
2.8.4. 自动配置的 ReactiveHealthIndicator
在适当的时候,Spring Boot 会自动配置以下 ReactiveHealthIndicators
钥匙 | 姓名 | 描述 |
---|---|---|
cassandra |
CassandraDriverReactiveHealthIndicator |
检查 Cassandra 数据库是否已启动 |
couchbase |
CouchbaseReactiveHealthIndicator |
检查 Couchbase 集群是否已启动 |
elasticsearch |
ElasticsearchReactiveHealthIndicator |
检查 Elasticsearch 集群是否已启动 |
mongo |
MongoReactiveHealthIndicator |
检查 Mongo 数据库是否已启动 |
neo4j |
Neo4jReactiveHealthIndicator |
检查 Neo4j 数据库是否已启动 |
redis |
RedisReactiveHealthIndicator |
检查 Redis 服务器是否已启动 |
如有必要,反应式指标会取代常规指标。此外,任何未明确处理的
HealthIndicator
都会被自动包装。
2.8.5. Health Groups
有时将健康指标组织成可用于不同目的的组很有用。
要创建运行状况指标组,您可以使用该management.endpoint.health.group.<name>
属性并将运行状况指标 ID 列表指定为include
或exclude
。例如,要创建仅包含数据库指标的组,您可以定义以下内容:
management.endpoint.health.group.custom.include=db
然后,您可以通过访问 localhost:8080/actuator/health/custom
来检查结果。
同样,要创建一个从组中排除数据库指标并包含所有其他指标的组,您可以定义以下内容:
management.endpoint.health.group.custom.exclude=db
默认情况下,组继承与系统运行状况相同的 StatusAggregator
和 HttpCodeStatusMapper
设置。但是,您也可以在每个组的基础上定义这些。如果需要,您还可以覆盖 show-details
和 roles
属性:
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
如果您需要注册自定义
StatusAggregator
或HttpCodeStatusMapper
bean 以与组一起使用,则可以使用@Qualifier("groupname")
健康组还可以包括/排除 CompositeHealthContributor
。您还可以仅包含/排除 CompositeHealthContributor
的某个组件。这可以使用组件的完全限定名称来完成,如下所示:
management.endpoint.health.group.custom.include="test/primary"
management.endpoint.health.group.custom.exclude="test/primary/b"
在上面的示例中,custom
组将包含 HealthContributor
,其名称为 primary
,是组合 test
的一个组件。在这里,primary
本身是一个组合体,名称为 b
的 HealthContributor
将被排除在 custom
组之外。
可以在主端口或管理端口上的附加路径上提供健康组。这在 Kubernetes 等云环境中很有用,在这些环境中,出于安全目的,为执行器端点使用单独的管理端口是很常见的。拥有一个单独的端口可能会导致不可靠的健康检查,因为即使健康检查成功,主应用程序也可能无法正常工作。可以为健康组配置额外的路径,如下所示:
management.endpoint.health.group.live.additional-path="server:/healthz"
这将使 live
健康组在主服务器端口上可用 /healthz
。前缀是强制性的,必须是 server:
(表示主服务器端口)或 management:
(表示管理端口,如果已配置)。路径必须是单个路径段。
2.8.6. DataSource Health
DataSource
健康指标显示标准数据源和路由数据源 bean 的运行状况。路由数据源的健康状况包括其每个目标数据源的健康状况。在健康端点的响应中,每个路由数据源的目标都使用其路由键命名。如果您不想在指标的输出中包含路由数据源,请设置 management.health.db.ignore-routing-data-sources
为 true
2.9. Kubernetes 探针(Probe)
部署在 Kubernetes 上的应用程序可以通过 Container Probes 提供有关其内部状态的信息。根据 您的 Kubernetes 配置 ,kubelet 会调用这些探针并对结果做出反应。
默认情况下,Spring Boot 管理您的 应用程序可用性状态 。如果部署在 Kubernetes 环境中,actuator 从 ApplicationAvailability
接口收集 “Liveness” 和 “Readiness” 信息,并在专用的 健康指标 中使用该信息:LivenessStateHealthIndicator
和 ReadinessStateHealthIndicator
。这些指标显示在全局健康端点 ( "/actuator/health"
) 上。它们还通过使用 健康组 ( "/actuator/health/liveness"
和 "/actuator/health/readiness"
)公开为单个 HTTP 探针。
然后,您可以使用以下端点信息配置 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>
应设置为执行器端点可用的端口。如果已设置management.server.port
属性,它可能是主 Web 服务器端口或单独的管理端口。
只有当应用程序 在 Kubernetes 环境中运行时 ,这些健康组才会自动启用。您可以使用 management.endpoint.health.probes.enabled
配置属性在任何环境中启用它们。
如果应用程序的启动时间比配置的活跃期(liveness period)更长,Kubernetes 提到
startupProbe
是一个可能的解决方案。这里不一定需要startupProbe
,因为在readinessProbe
在所有启动任务完成之前都会失败。请参阅 how probes behave during the application lifecycle
如果您的 Actuator 端点部署在单独的管理上下文中,则端点不会使用与主应用程序相同的 Web 基础设施(端口、连接池、框架组件)。在这种情况下,即使主应用程序无法正常工作(例如,它不能接受新连接),探针检查也可能会成功。出于这个原因,让主服务器端口上的 liveness
和 readiness
健康组可用是一个好主意。这可以通过设置以下属性来完成:
management.endpoint.health.probes.add-additional-paths=true
这将使 liveness
( /livez
)和 readiness
( readyz
)在主服务器端口可用
2.9.1. 使用 Kubernetes 探针检查外部状态
Actuator 将 “liveness” 和 “readiness” 探针配置为 Health Groups 。这意味着他们可以使用所有 健康组功能 。例如,您可以配置其他健康指标:
management.endpoint.health.group.readiness.include=readinessState,customCheck
默认情况下,Spring Boot 不会向这些组添加其他健康指标。
liveness
探针不应依赖于外部系统的健康检查。如果 应用程序的 liveness 状态 被破坏,Kubernetes 会尝试通过重新启动应用程序实例来解决该问题。这意味着如果外部系统(例如数据库、Web API 或外部缓存)发生故障,Kubernetes 可能会重新启动所有应用程序实例并产生级联故障。
至于 readiness
探针,应用程序开发人员必须仔细选择检查外部系统。出于这个原因,Spring Boot 在 readiness
探针中不包括任何额外的健康检查。如果 应用程序实例的 readiness
状态 未就绪,Kubernetes 不会将流量路由到该实例。某些外部系统可能不被应用程序实例共享,在这种情况下,它们可以包含在 readiness
探针中。其他外部系统可能对应用程序不是必需的(应用程序可能有断路器(circuit breakers)和回退(fallbacks)),在这种情况下,它们绝对不应该包括在内。不幸的是,所有应用程序实例共享的外部系统是常见的,您必须做出判断:将其包含在 readiness
探针中,并期望在外部服务关闭时应用程序停止服务或将其排除在外并处理堆栈更高的故障,也许通过在调用者中使用断路器。
如果应用程序的所有实例都未就绪,则具有
type=ClusterIP
或NodePort
的 Kubernetes 服务不接受任何传入连接。没有 HTTP 错误响应(503 等),因为没有连接。具有type=LoadBalancer
的服务可能会或不会接受连接,具体取决于供应商。具有显式 入口(ingress) 的服务也会以取决于实现的方式响应—— 入口服务本身必须决定如何处理来自下游的“连接被拒绝”。在负载均衡器和入口的情况下,很可能出现 HTTP 503
此外,如果应用程序使用 Kubernetes 自动缩放 ,它可能会对从负载均衡器中取出的应用程序做出不同的反应,具体取决于其自动缩放器配置。
2.9.2. 应用程序生命周期和探针状态
Kubernetes Probes 支持的一个重要方面是它与应用程序生命周期的一致性。AvailabilityState
(这是应用程序的内存中的内部状态)和实际的探针(公开该状态)之间存在显着差异。根据应用程序生命周期的阶段,探针可能不可用。
Spring Boot 在启动和关闭期间发布应用程序事件 ,探针可以监听此类事件并公开 AvailabilityState
信息。
下表显示了 HTTP 连接器在不同阶段的 AvailabilityState
和状态
当 Spring Boot 应用程序启动时:
Startup phase | LivenessState | ReadinessState | HTTP server | Notes |
---|---|---|---|---|
Starting | BROKEN |
REFUSING_TRAFFIC |
Not started | Kubernetes 检查 liveness Probe ,如果时间过长则重新启动应用程序 |
Started | CORRECT |
REFUSING_TRAFFIC |
Refuses requests | 应用上下文被刷新。应用程序执行启动任务,但尚未接收流量 |
Ready | CORRECT |
ACCEPTING_TRAFFIC |
Accepts requests | 启动任务完成。应用程序正在接收流量 |
当 Spring Boot 应用程序关闭时:
Shutdown phase | Liveness State | Readiness State | HTTP server | Notes |
---|---|---|---|---|
Running | CORRECT |
ACCEPTING_TRAFFIC |
接受请求 | 已请求关机 |
Graceful shutdown | CORRECT |
REFUSING_TRAFFIC |
新请求被拒绝 | 如果启用,优雅关闭处理正在进行的请求 |
Shutdown complete | N/A | N/A | 服务器已关闭 | 应用上下文关闭,应用程序关闭 |
有关 Kubernetes 部署的更多信息,请参阅 Kubernetes 容器生命周期部分
2.10. 应用信息
应用程序信息公开了您的 ApplicationContext
里定义的所有 InfoContributor
bean 收集的各种信息。Spring Boot 包含许多自动配置的 InfoContributor
bean ,您可以编写自己的。
2.10.1. 自动配置的 InfoContributors
在适当的时候,Spring 会自动配置以下 InfoContributor
bean :
ID | Name | 描述 | 先决条件 |
---|---|---|---|
build |
BuildInfoContributor |
公开构建信息 | META-INF/build-info.properties |
env |
EnvironmentInfoContributor |
公开 Environment 中名称以 info. 开头的任何属性 |
None |
git |
GitInfoContributor |
公开 git 信息 | git.properties |
java |
JavaInfoContributor |
公开 Java 运行时信息 | None |
是否启用单个贡献者由 management.info.<id>.enabled
属性控制。不同的贡献者对此属性有不同的默认值,这取决于他们的先决条件和他们公开的信息的性质。
没有先决条件表明应该启用它们,默认情况下禁用 env
和 java
贡献者。您可以通过将 management.info.env.enabled
或 management.info.java.enabled
属性设置为 true
来启用它们。
build
和 git
信息贡献者默认启用。每个都可以通过将 management.info.<id>.enabled
属性设置为 false
来禁用。或者,要禁用通常默认启用的每个贡献者,请将 management.info.defaults.enabled
属性设置为 false
2.10.2. 自定义应用程序信息
启用 env
贡献者后,您可以通过设置 Spring 属性 info.*
来自定义 info
端点公开的数据。info
键下的所有 Environment
属性都会自动公开。例如,您可以将以下设置添加到 application.properties
文件中:
info.app.encoding=UTF-8
info.app.java.source=11
info.app.java.target=11
除了硬编码这些值,您还可以 在构建时扩展 info 属性。假设您使用 Maven,您可以将前面的示例重写如下:
info.app.encoding=@project.build.sourceEncoding@ info.app.java.source=@java.version@ info.app.java.target=@java.version@
2.10.3. Git 提交信息
info
端点的另一个有用特性是它能够在项目构建时发布有关 git
源代码存储库状态的信息。如果 GitProperties
bean 可用,您可以使用 info
端点来公开这些属性。
如果
git.properties
文件在类路径的根目录可用,则自动配置GitProperties
bean 。请参阅 如何生成 git 信息
默认情况下,端点公开 git.branch
、git.commit.id
和 git.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
2.10.4. 构建信息
如果 BuildProperties
bean 可用,info
端点还可以发布有关您的构建的信息。如果类路径中有 META-INF/build-info.properties
文件可用,则会发生这种情况。
Maven 和 Gradle 插件都可以生成该文件。有关详细信息,请参阅 如何生成构建信息
2.10.5. Java 信息
info
端点发布有关您的 Java 运行时环境的信息,请参阅 JavaInfo
2.10.6. 编写自定义 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"
}
}
3. 通过 HTTP 进行监视和管理
如果您正在开发 Web 应用程序,Spring Boot Actuator 会自动配置所有启用的端点以通过 HTTP 公开。默认约定是使用前缀为 /actuator
的 id 端点的作为 URL 路径。例如,health
公开为 /actuator/health
Spring MVC,Spring WebFlux 和 Jersey 原生支持 Actuator 。如果 Jersey 和 Spring MVC 都可用,则使用 Spring MVC
3.1. 自定义管理端点路径
有时,自定义管理端点的前缀很有用。例如,您的应用程序可能已经将 /actuator
用于其他用途。您可以使用 management.endpoints.web.base-path
属性来更改管理端点的前缀,如以下示例所示:
management.endpoints.web.base-path=/manage
前面的 application.properties
示例将端点从 /actuator/{id}
更改为 /manage/{id}
(例如 /manage/info
)。
除非管理端口已经被配置为 使用不同的 HTTP 端口公开端点 ,否则
management.endpoints.web.xml-path
相对于server.servlet.context-path
(用于 servlet web 应用程序) 或spring.webflux.base-path
(用于反应式 web 应用程序) 。如果配置了management.server.port
,那么management.endpoints.web.xml-path
相对于management.server.base-path
如果要将端点映射到其他路径,则可以使用 management.endpoints.web.path-mapping
属性。
以下示例重新映射 /actuator/health
到 /healthcheck
management.endpoints.web.base-path=/
management.endpoints.web.path-mapping.health=healthcheck
3.2. 自定义管理服务器端口
对于基于云的部署,通过使用默认的 HTTP 端口公开管理端点是明智的选择。但是,如果您的应用程序在自己的数据中心内运行,则您可能更喜欢使用其他 HTTP 端口公开端点。
您可以设置 management.server.port
属性以更改 HTTP 端口,如以下示例所示:
management.server.port=8081
在 Cloud Foundry 上,默认情况下,应用程序仅在端口
8080
上接收HTTP和TCP路由请求。如果要在 Cloud Foundry 上使用自定义管理端口,则需要明确设置应用程序的路由以将流量转发到自定义端口。
3.3. 配置特定于管理的 SSL
当配置为使用自定义端口时,还可以通过使用各种 management.server.ssl.*
属性将管理服务器配置为其自己的 SSL 。例如,这样做可以使管理服务器通过 HTTP 可用,而主应用程序使用 HTTPS ,如以下属性设置所示:
server.port=8443
server.ssl.enabled=true
server.ssl.key-store=classpath:store.jks
server.ssl.key-password=secret
management.server.port=8080
management.server.ssl.enabled=false
或者,主服务器和管理服务器都可以使用 SSL ,但具有不同的密钥存储,如下所示:
server.port=8443
server.ssl.enabled=true
server.ssl.key-store=classpath:main.jks
server.ssl.key-password=secret
management.server.port=8080
management.server.ssl.enabled=true
management.server.ssl.key-store=classpath:management.jks
management.server.ssl.key-password=secret
3.4. 自定义管理服务器地址
您可以通过设置 management.server.address
属性来自定义管理端点可用的地址。如果您只想在内部或面向操作的网络上监听或仅监听来自 localhost
的连接,则这样做很有用。
只有当端口与主服务器端口不同时,您可以在不同的地址监听。
以下 application.properties
示例不允许远程管理连接:
management.server.port=8081
management.server.address=127.0.0.1
3.5. 禁用 HTTP 端点
如果您不想通过 HTTP 公开端点,则可以将管理端口设置为 -1
,如以下示例所示:
management.server.port=-1
也可以使用 management.endpoints.web.exposure.exclude
属性来实现,如以下示例所示:
management.endpoints.web.exposure.exclude=*
也可以公开所有端点:
management.endpoints.web.exposure.include=*
todo 4. 通过 JMX 进行监视和管理
5. Loggers
Spring Boot Actuator 可以在运行时查看和配置应用程序的日志级别。您可以查看整个列表,也可以查看单个记录器的配置,该配置由显式配置的记录级别以及由日志记录框架赋予它的有效记录级别组成。这些级别可以是以下之一:
TRACE
DEBUG
INFO
WARN
ERROR
FATAL
OFF
null
null
表示没有显式配置。
5.1. 配置 Logger
要配置给定的 Logger ,POST
请求到资源 URI 的部分实体,如以下示例所示:
{
"configuredLevel": "DEBUG"
}
要“重置”记录器的特定级别(并使用默认配置),可以传递
null
值给configuredLevel
示例
例如修改 root
日志级别:
Post
请求,发送 JSON 参数:
http://localhost:8080/actuator/loggers/root
{
"configuredLevel": "DEBUG"
}
6. 指标(Metrics)
Spring Boot Actuator 为 Micrometer 提供了依赖项管理和自动配置,Micrometer 是一种支持 众多监视系统 的应用程序指标外观,包括:
- AppOptics
- Atlas
- Datadog
- Dynatrace
- Elastic
- Ganglia
- Graphite
- Humio
- Influx
- JMX
- KairosDB
- New Relic
- Prometheus
- SignalFx
- Simple (in-memory)
- Stackdriver
- StatsD
- Wavefront
6.1. 入门
Spring Boot 自动配置组合 MeterRegistry
,并为其在类路径上找到的每个受支持的实现向组合添加注册。在运行时类路径中具有 micrometer-registry-{system}
依赖项足以让 Spring Boot 配置注册。
大多数注册具有共同的特征。例如,即使 Micrometer 注册实现位于类路径中,您也可以禁用特定的注册。例如,禁用 Datadog
management.metrics.export.datadog.enabled=false
除非特定于注册表的属性另有说明,否则您还可以禁用所有注册表,如以下示例所示:
management.metrics.export.defaults.enabled=false
Spring Boot 还会将任何自动配置的注册添加到 Metrics
类的全局静态复合注册表中,除非您明确告诉它不要:
management.metrics.use-global-registry=false
您可以注册任意数量的 MeterRegistryCustomizer
bean 来进一步配置注册表,例如应用通用标签,然后再向注册表注册任何计量器:
import io.micrometer.core.instrument.MeterRegistry;
import org.springframework.boot.actuate.autoconfigure.metrics.MeterRegistryCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration(proxyBeanMethods = false)
public class MyMeterRegistryConfiguration {
@Bean
public MeterRegistryCustomizer<MeterRegistry> metricsCommonTags() {
return (registry) -> registry.config().commonTags("region", "us-east-1");
}
}
您可以通过更具体地了解泛型类型,将自定义项应用于特定的注册表实现:
import io.micrometer.core.instrument.Meter;
import io.micrometer.core.instrument.config.NamingConvention;
import io.micrometer.graphite.GraphiteMeterRegistry;
import org.springframework.boot.actuate.autoconfigure.metrics.MeterRegistryCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration(proxyBeanMethods = false)
public class MyMeterRegistryConfiguration {
@Bean
public MeterRegistryCustomizer<GraphiteMeterRegistry> graphiteMetricsNamingConvention() {
return (registry) -> registry.config().namingConvention(this::name);
}
private String name(String name, Meter.Type type, String baseUnit) {
return ...
}
}
Spring Boot 还配置了您可以通过配置或专用注解标记控制的 内置检测
todo 6.2. 支持的监控系统
- AppOptics
- Atlas
- Datadog
- Dynatrace
- Elastic
- Ganglia
- Graphite
- Humio
- Influx
- JMX
- KairosDB
- New Relic
- Prometheus
- SignalFx
- Simple
- Stackdriver
- StatsD
- Wavefront
todo 6.3. 支持的指标(Metrics)和计量器(Meters)
Spring Boot 为多种技术提供自动计量器注册。在大多数情况下,默认值提供了可以发布到任何受支持的监控系统的合理指标。
-
JVM 指标
- 各种内存和缓冲池
- 垃圾回收相关统计
- 线程利用率
- 加载和卸载的类数
-
系统指标
- CPU 指标
- 文件描述符指标
- 正常运行时间指标(应用程序运行的时间量和绝对启动时间的固定指标)
- 可用磁盘空间
-
应用程序启动指标
application.started.time
: 启动应用程序所用的时间。application.ready.time
:应用程序准备好为请求提供服务所需的时间。
-
记录器指标
-
任务执行和调度指标
-
Spring MVC 指标
-
Spring WebFlux 指标
-
Jersey 服务器指标
-
HTTP Client 指标
-
Tomcat 指标
-
缓存指标
-
数据源指标
-
Hibernate 指标
-
Spring Data 存储库指标
-
RabbitMQ 指标
-
Spring Integration 指标
-
Kafka 指标
-
MongoDB 指标
-
Jetty 指标
-
@Timed
注解支持 -
Redis 指标
6.4. 注册自定义指标
要注册自定义指标,请注入 MeterRegistry
到您的组件中,如以下示例所示:
import io.micrometer.core.instrument.MeterRegistry;
import io.micrometer.core.instrument.Tags;
import org.springframework.stereotype.Component;
@Component
public class MyBean {
private final Dictionary dictionary;
public MyBean(MeterRegistry registry) {
this.dictionary = Dictionary.load();
registry.gauge("dictionary.size", Tags.empty(), this.dictionary.getWords().size());
}
}
如果您的指标依赖于其他 bean,我们建议您使用 MeterBinder
来注册它们:
import io.micrometer.core.instrument.Gauge;
import io.micrometer.core.instrument.binder.MeterBinder;
import org.springframework.context.annotation.Bean;
public class MyMeterBinderConfiguration {
@Bean
public MeterBinder queueSize(Queue queue) {
return (registry) -> Gauge.builder("queueSize", queue::size).register(registry);
}
}
使用 MeterBinder
可确保设置正确的依赖关系,并且在检索度量值时 bean 可用。如果您发现您反复检测跨组件或应用程序的一组指标,则 MeterBinder
实现也可能很有用。
默认情况下,来自所有
MeterBinder
bean 的指标会自动绑定到 Spring 管理的MeterRegistry
6.5. 自定义单个指标
如果需要将自定义应用于特定 Meter
实例,可以使用 io.micrometer.core.instrument.config.MeterFilter
接口。
例如,如果要将所有以 com.example
开头的计量器 ID 的 mytag.region
标签重命名为 mytag.area
,则可以执行以下操作:
import io.micrometer.core.instrument.config.MeterFilter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration(proxyBeanMethods = false)
public class MyMetricsFilterConfiguration {
@Bean
public MeterFilter renameRegionTagMeterFilter() {
return MeterFilter.renameTag("com.example", "mytag.region", "mytag.area");
}
}
默认情况下,所有
MeterFilter
bean 都自动绑定到 Spring 管理的MeterRegistry
。确保使用 Spring 管理的MeterRegistry
而不是Metrics
上的任何静态方法来注册您的指标。这些使用非 Spring 管理的全局注册表。
6.5.1. 通用标签
通用标签通常用于在操作环境(如主机,实例,区域,堆栈等)上进行维度深入分析。通用标签适用于所有计量器,并可以按以下示例所示进行配置:
management.metrics.tags.region=us-east-1
management.metrics.tags.stack=prod
上面的示例将 region
和 stack
标记分别添加到具有 us-east-1
和 prod
的值的所有计量器。
如果使用 Graphite ,则通用标签的顺序很重要。由于使用这种方法不能保证通用标签的顺序,因此建议 Graphite 用户定义一个自定义
MeterFilter
6.5.2. Per-meter 属性
除了 MeterFilter
bean ,还可以使用属性在 per-meter 的基础上应用一组有限的自定义设置。per-meter 自定义适用于以给定名称开头的所有计量器 ID 。例如,以下将禁用所有以 example.remote
开头的计量器 ID
management.metrics.enable.example.remote=false
以下属性允许按 per-meter 自定义:
属性 | 描述 |
---|---|
management.metrics.enable |
是否阻止计量器发出任何指标 |
management.metrics.distribution.percentiles-histogram |
是否发布适合计算可聚合(跨维度)百分位近似值的直方图 |
management.metrics.distribution.minimum-expected-value management.metrics.distribution.maximum-expected-value |
通过限制期望值的范围来发布较少的直方图桶 |
management.metrics.distribution.percentiles |
发布在您的应用程序中计算的百分位数 |
management.metrics.distribution.expiry management.metrics.distribution.buffer-length |
通过在可配置的到期后旋转的环形缓冲区中累积最近的样本,赋予它们更大的权重,并具有可配置的缓冲区长度 |
management.metrics.distribution.slo |
发布包含由您的服务级别目标定义的存储桶的累积直方图 |
有关 percentiles-histogram
,percentiles
和 sla
的更多细节,请参阅 “Histograms and percentiles” section
6.6. 指标端点
Spring Boot 提供了一个metrics
端点,可用于诊断检查应用程序收集的指标。端点默认情况下不可用,必须公开。
导航 /actuator/metrics
显示可用仪表名称的列表。您可以通过提供特定的仪表名称作为选择器来向下浏览以查看有关该仪表的信息,例如 /actuator/metrics/jvm.memory.max
您在此处使用的名称应与代码中使用的名称相匹配,而不是将其作为监控系统的标准化命名约定后的名称。换句话说,如果
jvm.memory.max
在 Prometheus 中显示为jvm memory max
,因为它的变数命名原则是蛇形的,那么在检查指标端点的计量器时,仍然应该使用jvm.memory.max
作为选择器。
您还可以在 URL 的末尾添加任意数量的 tag=KEY:VALUE
查询参数,以在维度上进一步细分计量器,例如 /actuator/metrics/jvm.memory.max?tag=area:nonheap
报告的测量值是与计量器名称和已应用的任何标签相匹配的所有计量器的统计信息的总和。因此,在上面的示例中,返回的“值”统计量是堆的“代码缓存”,“压缩类空间”和“元空间”区域的最大内存占用量的总和。如果您只想查看 Metaspace 的最大大小,则可以添加一个额外的
tag=id:Metaspace
,即/actuator/metrics/jvm.memory.max?tag=area:nonheap&tag=id:Metaspace
7. 审计(Auditing)
一旦 Spring Security 发挥作用,Spring Boot Actuator 将拥有一个灵活的审计框架来发布事件(默认情况下,“身份验证成功”,“失败”和“拒绝访问”异常)。此功能对于基于身份验证失败的报告和实施锁定策略非常有用。
可以通过在应用程序的配置中提供 AuditEventRepository
类型的 bean 来启用审计。为了方便起见,Spring Boot 提供了 InMemoryAuditEventRepository
。 InMemoryAuditEventRepository
功能有限,我们建议仅将其用于开发环境。对于生产环境,请考虑创建自己的替代 AuditEventRepository
实现。
7.1. 自定义审计
要自定义已发布的安全事件,可以提供自己的 AbstractAuthenticationAuditListener
和 AbstractAuthorizationAuditListener
实现。
您也可以将审计服务用于自己的业务事件。为此,可以将 AuditEventRepository
bean 注入您自己的组件中,然后直接使用它,也可以使用 Spring ApplicationEventPublisher
发布 AuditApplicationEvent
(通过实现 ApplicationEventPublisherAware
)。
8. HTTP 跟踪(HTTP Tracing)
可以通过在应用程序的配置中提供 HttpTraceRepository
类型的 bean 来启用 HTTP 跟踪。为了方便起见,Spring Boot 提供了一个默认存储最后 100个 请求-响应交换的跟踪的 InMemoryHttpTraceRepository
。 InMemoryHttpTraceRepository
与其他跟踪解决方案相比,它受到限制,我们建议仅将其用于开发环境。对于生产环境,建议使用可用于生产的跟踪或可观察性解决方案,例如 Zipkin 或 Spring Cloud Sleuth 。或者,创建自己的 HttpTraceRepository
httptrace
端点可以被用来获得关于被存储在 HttpTraceRepository
中的请求-响应交换信息。
8.1. 自定义 HTTP 跟踪
要自定义每个跟踪中包含的项目,请使用 management.trace.http.include
配置属性。对于高级定制,请考虑注册自己的 HttpExchangeTracer
实现。
9. 过程监控(Process Monitoring)
在 spring-boot
模块中,您可以找到两个类来创建通常对进程监控有用的文件:
ApplicationPidFileWriter
创建一个包含应用程序PID的文件(默认情况下,在应用程序目录中的文件名为application.pid
)WebServerPortFileWriter
创建一个文件(一个或多个),其中包含正在运行的 Web 服务器的端口(默认情况下,在应用程序目录中,文件名为application.port
)。
默认情况下,不会激活这些类,但是您可以通过以下方式启用:
9.1. 扩展配置
在 META-INF/spring.factories
文件中,您可以激活写入 PID 文件的监听器,如以下示例所示:
org.springframework.context.ApplicationListener=\
org.springframework.boot.context.ApplicationPidFileWriter,\
org.springframework.boot.web.context.WebServerPortFileWriter
9.2. 以编程方式启用过程监控
您也可以通过调用 SpringApplication.addListeners(..)
方法并传递适当的 Writer
对象来激活监听器。此方法还允许您自定义 Writer
构造函数中的文件名和路径。
10. Cloud Foundry 支持
Spring Boot 的执行器模块包括额外的支持,当您将其部署到兼容的 Cloud Foundry 实例时就会激活。/cloudfoundryapplication
路径提供了通往所有 @Endpoint
bean 的替代安全路由。
扩展支持使 Cloud Foundry 管理 UI(例如可用于查看已部署的应用程序的 Web 应用程序)增加了 Spring Boot 执行器信息。例如,应用程序状态页面可能包含完整的运行状况信息,而不是典型的 running
或 stopped
状态。
普通用户不能直接访问
/cloudfoundryapplication
路径。要使用端点,您必须在请求中传递有效的 UAA 令牌。
10.1. 禁用扩展的 Cloud Foundry 执行器支持
如果要完全禁用 /cloudfoundryapplication
端点,可以将以下设置添加到 application.properties
文件中:
management.cloudfoundry.enabled=false
10.2. Cloud Foundry 自签名证书
默认情况下,/cloudfoundryapplication
端点的安全性验证会对各种 Cloud Foundry 服务进行 SSL 调用。如果您的 Cloud Foundry UAA 或 Cloud Controller 服务使用自签名证书,则需要设置以下属性:
management.cloudfoundry.skip-ssl-validation=true
10.3. 自定义上下文路径
如果服务器的上下文路径已配置为 /
以外的任何其他值,则 Cloud Foundry 端点在应用程序的根目录将不可用。例如,如果 server.servlet.context-path=/app
,Cloud Foundry 端点将可用 /app/cloudfoundryapplication/*
如果您希望 Cloud Foundry 端点始终在 /cloudfoundryapplication/*
处可用,而与服务器的上下文路径无关,则需要在应用程序中进行显式配置。配置将根据所使用的 Web 服务器而有所不同。对于 Tomcat ,可以添加以下配置:
import java.io.IOException;
import java.util.Collections;
import javax.servlet.GenericServlet;
import javax.servlet.Servlet;
import javax.servlet.ServletContainerInitializer;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import org.apache.catalina.Host;
import org.apache.catalina.core.StandardContext;
import org.apache.catalina.startup.Tomcat;
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
import org.springframework.boot.web.servlet.ServletContextInitializer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration(proxyBeanMethods = false)
public class MyCloudFoundryConfiguration {
@Bean
public TomcatServletWebServerFactory servletWebServerFactory() {
return new TomcatServletWebServerFactory() {
@Override
protected void prepareContext(Host host, ServletContextInitializer[] initializers) {
super.prepareContext(host, initializers);
StandardContext child = new StandardContext();
child.addLifecycleListener(new Tomcat.FixContextListener());
child.setPath("/cloudfoundryapplication");
ServletContainerInitializer initializer = getServletContextInitializer(getContextPath());
child.addServletContainerInitializer(initializer, Collections.emptySet());
child.setCrossContext(true);
host.addChild(child);
}
};
}
private ServletContainerInitializer getServletContextInitializer(String contextPath) {
return (classes, context) -> {
Servlet servlet = new GenericServlet() {
@Override
public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
ServletContext context = req.getServletContext().getContext(contextPath);
context.getRequestDispatcher("/cloudfoundryapplication").forward(req, res);
}
};
context.addServlet("cloudfoundry", servlet).addMapping("/*");
};
}
}