Java编程中的Spring Boot Actuator使用
一、Spring Boot Actuator 简介
Spring Boot Actuator 是 Spring Boot 提供的一个强大的功能模块,它为 Spring Boot 应用程序添加了生产就绪(production - ready)特性,使得我们可以在应用运行时对其进行监控和管理。这些特性包括健康检查、指标收集、环境信息查看、线程转储、审计等,大大方便了开发人员在开发、测试以及生产环境中对应用程序的调试和维护。
在传统的 Java Web 应用开发中,要实现对应用状态的监控和管理,通常需要手动集成各种不同的工具和框架,这是一个复杂且耗时的过程。而 Spring Boot Actuator 基于 Spring Boot 的自动配置和约定大于配置的理念,将这些功能集成在一起,并且提供了统一且简洁的接口,让开发人员可以轻松地为应用程序添加这些关键功能。
二、Spring Boot Actuator 的依赖引入
在使用 Spring Boot Actuator 之前,我们需要在项目中引入相应的依赖。如果使用的是 Maven 构建工具,在 pom.xml
文件中添加如下依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
如果使用 Gradle 构建工具,在 build.gradle
文件中添加:
implementation 'org.springframework.boot:spring-boot-starter-actuator'
引入依赖后,Spring Boot 会自动配置 Actuator 的相关端点(endpoints),这些端点就是我们与 Actuator 交互,获取应用程序运行时信息的接口。
三、Actuator 端点详解
- 健康检查端点(/actuator/health)
- 功能:健康检查端点用于检查应用程序的健康状况。它会聚合多个健康指标检查器(health indicators)的结果,返回应用程序是否健康的总体状态。常见的健康指标检查包括数据库连接是否正常、外部服务是否可达等。
- 示例:假设我们的应用程序连接了一个 MySQL 数据库,Actuator 会自动配置一个
DataSourceHealthIndicator
来检查数据库连接的健康状况。当我们访问/actuator/health
端点时,如果数据库连接正常,返回结果类似如下:
{
"status": "UP",
"components": {
"db": {
"status": "UP",
"details": {
"database": "MySQL",
"hello": 1
}
}
}
}
如果数据库连接出现问题,status
可能会变为 DOWN
,并且在 details
中会包含具体的错误信息,帮助我们快速定位问题。
- 自定义健康检查:除了默认的健康检查器,我们还可以自定义健康检查逻辑。例如,假设我们的应用程序依赖于一个外部 RESTful 服务,我们可以创建一个自定义的健康检查器:
import org.springframework.boot.actuate.health.Health;
import org.springframework.boot.actuate.health.HealthIndicator;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;
@Component
public class ExternalServiceHealthIndicator implements HealthIndicator {
private final RestTemplate restTemplate;
public ExternalServiceHealthIndicator(RestTemplate restTemplate) {
this.restTemplate = restTemplate;
}
@Override
public Health health() {
try {
// 尝试调用外部服务
restTemplate.getForObject("http://external - service - url/status", String.class);
return Health.up().build();
} catch (Exception e) {
return Health.down(e).build();
}
}
}
这样,在健康检查时,就会同时检查这个外部服务的状态。
- 指标端点(/actuator/metrics)
- 功能:指标端点用于收集和展示应用程序的各种指标数据,如内存使用情况、CPU 使用率、HTTP 请求计数、响应时间等。这些指标数据对于了解应用程序的性能和资源使用情况非常有帮助。
- 示例:访问
/actuator/metrics
端点,会返回所有支持的指标列表:
{
"names": [
"jvm.memory.committed",
"jvm.memory.max",
"jvm.memory.used",
"http.server.requests"
]
}
如果我们想查看某个具体指标的详细信息,例如 jvm.memory.used
,可以访问 /actuator/metrics/jvm.memory.used
,返回结果如下:
{
"name": "jvm.memory.used",
"description": "The amount of used memory",
"baseUnit": "bytes",
"measurements": [
{
"statistic": "VALUE",
"value": 123456789
}
],
"availableTags": [
{
"tag": "area",
"values": [
"heap",
"non - heap"
]
},
{
"tag": "id",
"values": [
"Compressed Class Space",
"Metaspace",
"PS Eden Space",
"PS Old Gen",
"PS Survivor Space"
]
}
]
}
这里显示了已使用内存的字节数,并且还提供了可以进一步细分指标的标签信息。 - 自定义指标:我们也可以自定义指标来收集特定业务逻辑的相关数据。例如,假设我们有一个电商应用,想统计商品的浏览次数,可以这样定义自定义指标:
import io.micrometer.core.instrument.Counter;
import io.micrometer.core.instrument.MeterRegistry;
import org.springframework.stereotype.Service;
@Service
public class ProductService {
private final Counter productViewCounter;
public ProductService(MeterRegistry meterRegistry) {
this.productViewCounter = meterRegistry.counter("product.views", "category", "all");
}
public void viewProduct() {
productViewCounter.increment();
}
}
然后在商品浏览的业务逻辑中调用 viewProduct()
方法,就会统计商品的浏览次数。通过 /actuator/metrics/product.views
端点可以查看这个自定义指标的数据。
- 环境端点(/actuator/env)
- 功能:环境端点用于查看应用程序当前的环境配置信息,包括系统属性、环境变量、Spring 配置文件中的属性等。这在排查配置相关问题时非常有用。
- 示例:访问
/actuator/env
端点,会返回一个 JSON 格式的配置信息,例如:
{
"activeProfiles": [
"prod"
],
"propertySources": [
{
"name": "systemProperties",
"source": {
"java.version": "11.0.12",
"java.home": "/usr/lib/jvm/java - 11 - openjdk - amd64",
"user.name": "user",
"user.home": "/home/user"
}
},
{
"name": "systemEnvironment",
"source": {
"PATH": "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
"LANG": "en_US.UTF - 8"
}
},
{
"name": "applicationConfig: [classpath:/application - prod.properties]",
"source": {
"spring.datasource.url": "jdbc:mysql://localhost:3306/mydb",
"spring.datasource.username": "root",
"spring.datasource.password": "password"
}
}
]
}
这里展示了活动的配置文件、系统属性、环境变量以及应用程序特定的配置属性。
- 线程转储端点(/actuator/threaddump)
- 功能:线程转储端点用于获取应用程序当前的线程信息,包括线程状态、堆栈跟踪等。当应用程序出现性能问题或死锁时,通过线程转储可以分析线程的执行情况,找出问题所在。
- 示例:访问
/actuator/threaddump
端点,会返回类似如下的文本信息:
"http - nio - 8080 - exec - 1" #24 daemon prio=5 os_prio=0 tid=0x00007f8d04019000 nid=0x3b4 runnable [0x00007f8d1747f000]
java.lang.Thread.State: RUNNABLE
at sun.nio.ch.NioSocketImpl.accept(Native Method)
at sun.nio.ch.NioServerSocketChannelImpl.accept(NioServerSocketChannelImpl.java:145)
at org.apache.tomcat.util.net.NioEndpoint$Acceptor.run(NioEndpoint.java:741)
at java.lang.Thread.run(Thread.java:834)
这里详细列出了每个线程的名称、优先级、状态以及堆栈跟踪信息。
- 审计端点(/actuator/auditevents)
- 功能:审计端点用于记录和展示应用程序的审计事件,例如用户登录、权限变更等重要操作。这些审计信息对于安全审计和问题追溯非常关键。
- 示例:要使用审计端点,首先需要配置审计事件发布器。例如,使用 Spring Security 时,可以这样配置:
import org.springframework.beans.factory.annotation.Autowired;
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.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository;
import org.springframework.security.web.authentication.rememberme.jdbc.JdbcTokenRepositoryImpl;
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;
import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler;
import org.springframework.security.web.authentication.session.ConcurrentSessionControlAuthenticationStrategy;
import org.springframework.security.web.authentication.session.RegisterSessionAuthenticationStrategy;
import org.springframework.security.web.authentication.session.SessionAuthenticationStrategy;
import org.springframework.security.web.savedrequest.HttpSessionRequestCache;
import org.springframework.security.web.savedrequest.RequestCache;
import org.springframework.security.web.savedrequest.SavedRequest;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.springframework.security.web.util.matcher.OrRequestMatcher;
import org.springframework.security.web.util.matcher.RequestMatcher;
import javax.sql.DataSource;
import java.util.ArrayList;
import java.util.List;
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private DataSource dataSource;
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/", "/home").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.permitAll()
.and()
.logout()
.permitAll();
http
.authenticationEventPublisher(authenticationEventPublisher());
}
@Bean
public PersistentTokenRepository persistentTokenRepository() {
JdbcTokenRepositoryImpl tokenRepository = new JdbcTokenRepositoryImpl();
tokenRepository.setDataSource(dataSource);
return tokenRepository;
}
@Bean
public SessionAuthenticationStrategy sessionAuthenticationStrategy() {
return new RegisterSessionAuthenticationStrategy(new ConcurrentSessionControlAuthenticationStrategy());
}
@Bean
public RequestCache requestCache() {
return new HttpSessionRequestCache();
}
@Bean
public LogoutSuccessHandler logoutSuccessHandler() {
SecurityContextLogoutHandler securityContextLogoutHandler = new SecurityContextLogoutHandler();
List<RequestMatcher> requestMatchers = new ArrayList<>();
requestMatchers.add(new AntPathRequestMatcher("/logout"));
requestMatchers.add(new OrRequestMatcher());
securityContextLogoutHandler.setLogoutRequestMatcher(new OrRequestMatcher(requestMatchers));
return securityContextLogoutHandler;
}
}
然后,当用户登录、注销等操作发生时,相关的审计事件会被记录。访问 /actuator/auditevents
端点可以查看这些审计事件的信息,例如:
[
{
"principal": "user",
"type": "AUTHENTICATION_SUCCESS",
"timestamp": "2023 - 01 - 01T12:00:00.000Z",
"data": {
"details": {
"remoteAddress": "192.168.1.100",
"sessionId": "1234567890abcdef"
}
}
}
]
这里记录了用户 user
的成功登录事件,以及相关的详细信息。
四、Actuator 端点的安全性配置
由于 Actuator 端点包含了应用程序的敏感信息,如配置信息、健康状况等,因此在生产环境中,必须对这些端点进行安全配置,以防止未经授权的访问。
- 使用 Spring Security 进行认证
- 添加依赖:如果项目中尚未使用 Spring Security,需要添加 Spring Security 依赖。对于 Maven 项目,在
pom.xml
中添加:
- 添加依赖:如果项目中尚未使用 Spring Security,需要添加 Spring Security 依赖。对于 Maven 项目,在
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
对于 Gradle 项目,在 build.gradle
中添加:
implementation 'org.springframework.boot:spring-boot-starter-security'
- **配置安全规则**:在 Spring Security 的配置类中,可以配置 Actuator 端点的访问权限。例如:
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.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/actuator/health").permitAll()
.antMatchers("/actuator/info").permitAll()
.antMatchers("/actuator/metrics").hasRole("ADMIN")
.antMatchers("/actuator/env").hasRole("ADMIN")
.anyRequest().authenticated()
.and()
.formLogin();
}
@Bean
@Override
public UserDetailsService userDetailsService() {
UserDetails user =
User.withDefaultPasswordEncoder()
.username("user")
.password("password")
.roles("USER")
.build();
UserDetails admin =
User.withDefaultPasswordEncoder()
.username("admin")
.password("adminpassword")
.roles("ADMIN")
.build();
return new InMemoryUserDetailsManager(user, admin);
}
}
在这个配置中,/actuator/health
和 /actuator/info
端点允许所有用户访问,而 /actuator/metrics
和 /actuator/env
端点只允许具有 ADMIN
角色的用户访问。
- 使用 HTTP Basic 认证
- 配置:如果使用 HTTP Basic 认证,可以在
application.properties
文件中配置用户名和密码:
- 配置:如果使用 HTTP Basic 认证,可以在
spring.security.user.name=admin
spring.security.user.password=adminpassword
然后在 Spring Security 配置类中配置使用 HTTP Basic 认证:
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.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.httpBasic()
.and()
.authorizeRequests()
.antMatchers("/actuator/health").permitAll()
.antMatchers("/actuator/info").permitAll()
.antMatchers("/actuator/metrics").hasRole("ADMIN")
.antMatchers("/actuator/env").hasRole("ADMIN")
.anyRequest().authenticated();
}
@Bean
@Override
public UserDetailsService userDetailsService() {
UserDetails user =
User.withDefaultPasswordEncoder()
.username("user")
.password("password")
.roles("USER")
.build();
UserDetails admin =
User.withDefaultPasswordEncoder()
.username("admin")
.password("adminpassword")
.roles("ADMIN")
.build();
return new InMemoryUserDetailsManager(user, admin);
}
}
这样,在访问受保护的 Actuator 端点时,会弹出 HTTP Basic 认证对话框,要求用户输入用户名和密码。
五、Actuator 端点的定制与扩展
- 定制端点的暴露方式
- 默认暴露情况:在 Spring Boot 2.x 中,默认情况下,只有
health
和info
端点是暴露的,并且是以 JSON 格式返回数据。如果要暴露其他端点,可以通过配置文件进行设置。 - 配置暴露端点:在
application.properties
文件中,可以使用management.endpoints.web.exposure.include
属性来指定要暴露的端点。例如,要暴露metrics
和env
端点,可以这样配置:
- 默认暴露情况:在 Spring Boot 2.x 中,默认情况下,只有
management.endpoints.web.exposure.include=health,info,metrics,env
如果要暴露所有端点,可以使用 *
:
management.endpoints.web.exposure.include=*
- 定制端点的路径
- 默认路径:Actuator 端点默认的路径前缀是
/actuator
,例如健康检查端点是/actuator/health
。如果想修改这个前缀,可以在application.properties
文件中配置:
- 默认路径:Actuator 端点默认的路径前缀是
management.endpoints.web.base - path=/management
这样,所有 Actuator 端点的路径前缀就变为 /management
,健康检查端点变为 /management/health
。
3. 扩展端点
- 创建自定义端点:假设我们想创建一个自定义的端点,用于获取应用程序中某个特定业务对象的状态。首先创建一个类,实现 Endpoint
接口:
import org.springframework.boot.actuate.endpoint.annotation.Endpoint;
import org.springframework.boot.actuate.endpoint.annotation.ReadOperation;
import org.springframework.stereotype.Component;
@Component
@Endpoint(id = "custom - endpoint")
public class CustomEndpoint {
@ReadOperation
public String getCustomStatus() {
// 这里编写获取特定业务对象状态的逻辑
return "Custom status is OK";
}
}
然后,通过配置暴露这个自定义端点:
management.endpoints.web.exposure.include=health,info,custom - endpoint
访问 /actuator/custom - endpoint
就可以获取自定义端点返回的信息。
六、在生产环境中使用 Actuator
- 监控与报警
- 结合监控工具:可以将 Actuator 与 Prometheus 和 Grafana 等监控工具结合使用。首先,引入 Micrometer Prometheus 依赖:
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer - registry - prometheus</artifactId>
</dependency>
然后配置 Prometheus 抓取 Actuator 暴露的指标数据。在 Prometheus 的配置文件 prometheus.yml
中添加如下配置:
scrape_configs:
- job_name: 'spring - boot - actuator'
static_configs:
- targets: ['your - app - host:your - app - port']
metrics_path: '/actuator/prometheus'
这样,Prometheus 就会定期从 Actuator 的 /actuator/prometheus
端点抓取指标数据。然后可以在 Grafana 中创建仪表盘,展示这些指标数据,实现对应用程序的实时监控。
- 设置报警规则:基于 Prometheus 收集的数据,可以在 Grafana 或其他报警工具(如 Alertmanager)中设置报警规则。例如,当应用程序的内存使用率超过 80% 时发送报警邮件。
2. 故障排查
- 利用健康检查和线程转储:在生产环境中,当应用程序出现故障时,首先可以通过健康检查端点确定应用程序的整体健康状况,快速定位是哪个组件出现问题。如果怀疑是线程死锁或性能问题,可以使用线程转储端点获取线程信息,分析线程的执行情况,找出问题所在。
- 查看环境和配置信息:如果应用程序出现配置相关的问题,通过环境端点查看当前应用程序的配置信息,对比预期的配置,找出配置错误。
通过以上对 Spring Boot Actuator 的详细介绍、代码示例以及在生产环境中的应用说明,相信开发者能够熟练掌握并运用 Actuator 为自己的 Spring Boot 应用程序添加强大的监控和管理功能,提升应用程序的可靠性和可维护性。