Spring Boot Actuator 学习笔记

概述

Spring Boot Actuator是Spring Boot提供的生产就绪功能模块,它为Spring Boot应用程序提供了很多监控和管理功能。通过Actuator,我们可以查看应用程序的内部状态、健康状况、指标信息、配置详情等。

Actuator提供了RESTful API端点,可以轻松集成到监控系统中,是微服务架构中不可或缺的组件。本教程将详细介绍Actuator的核心功能、配置方法以及在生产环境中的最佳实践。

核心价值与用途

应用监控:实时查看应用健康状况、性能指标(如请求数量、响应时间)、资源使用情况等。

问题诊断:当应用出现问题时,可以通过暴露的端点获取线程转储、堆内存信息、日志级别等,快速定位问题。

运行状况管理:提供就绪和存活状态探针,与 Kubernetes 等容器编排平台无缝集成,用于服务发现和滚动更新。

审计与管理:查看应用配置、环境变量、Bean 定义,甚至可以动态修改日志级别。

核心概念

端点(Endpoints)

端点是Actuator提供的REST API,每个端点都提供特定的功能:

应用配置类端点:显示应用程序的配置信息

指标类端点:显示应用程序的指标信息

操作控制类端点:提供关闭应用程序等操作

暴露方式

HTTP:通过HTTP请求访问端点

JMX:通过JMX MBean访问端点

WebSocket:通过WebSocket连接访问端点

环境准备

Maven依赖

java 复制代码
<dependencies>
    <!-- Spring Boot Actuator -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-actuator</artifactId>
    </dependency>

    <!-- Spring Boot Web -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    <!-- 监控指标 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-actuator</artifactId>
    </dependency>

    <!-- Micrometer (可选,用于自定义指标) -->
    <dependency>
        <groupId>io.micrometer</groupId>
        <artifactId>micrometer-registry-prometheus</artifactId>
    </dependency>

    <!-- 安全配置 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-security</artifactId>
    </dependency>
</dependencies>

基础配置

java 复制代码
server:
  port: 8080

management:
  endpoints:
    web:
      exposure:
        # 暴露所有端点
        include: "*"
      base-path: /actuator
  endpoint:
    shutdown:
      enabled: true
    health:
      show-details: when-authorized
  security:
    enabled: true

info:
  app:
    name: @project.name@
    description: @project.description@
    version: @project.version@
    java:
      version: @java.version@

内置端点

健康检查端点

java 复制代码
@RestController
@RequestMapping("/actuator/health")
public class HealthController {

    @Autowired
    private HealthIndicatorRegistry healthIndicatorRegistry;

    @GetMapping
    public Health health() {
        Health.Builder builder = Health.up();

        // 检查数据库连接
        try {
            // 数据库连接检查逻辑
            builder.withDetail("database", "连接正常");
        } catch (Exception e) {
            builder.down().withDetail("database", e.getMessage());
        }

        // 检查外部服务
        try {
            // 外部服务检查逻辑
            builder.withDetail("external-service", "服务正常");
        } catch (Exception e) {
            builder.status("WARN").withDetail("external-service", e.getMessage());
        }

        return builder.build();
    }
}

// 自定义健康指示器
@Component
public class CustomHealthIndicator implements HealthIndicator {

    @Override
    public Health health() {
        // 执行健康检查逻辑
        boolean healthy = checkHealth();

        if (healthy) {
            return Health.up()
                    .withDetail("status", "Custom service is running")
                    .build();
        } else {
            return Health.down()
                    .withDetail("error", "Custom service is down")
                    .build();
        }
    }

    private boolean checkHealth() {
        // 自定义健康检查逻辑
        return true;
    }
}

// 数据库健康指示器
@Configuration
public class DatabaseHealthConfig {

    @Bean
    public DataSourceHealthIndicator dataSourceHealthIndicator(DataSource dataSource) {
        return new DataSourceHealthIndicator(dataSource, "SELECT 1");
    }
}

应用信息端点

java 复制代码
@Configuration
public class InfoConfig {

    @Bean
    public InfoContributor customInfoContributor() {
        return builder -> {
            Map<String, Object> details = new HashMap<>();
            details.put("build", Map.of(
                "artifact", "my-app",
                "name", "My Application",
                "time", new Date().toString(),
                "version", "1.0.0",
                "group", "com.example"
            ));

            details.put("system", Map.of(
                "java.version", System.getProperty("java.version"),
                "os.name", System.getProperty("os.name"),
                "os.arch", System.getProperty("os.arch"),
                "processors", Runtime.getRuntime().availableProcessors()
            ));

            builder.withDetails(details);
        };
    }
}

// Git信息贡献者
@Configuration
public class GitInfoConfig {

    @Bean
    public GitInfoContributor gitInfoContributor() {
        return new GitInfoContributor();
    }
}

// 环境信息贡献者
@Configuration
public class EnvironmentInfoConfig {

    @Autowired
    private Environment environment;

    @Bean
    public InfoContributor environmentInfoContributor() {
        return builder -> {
            Map<String, Object> envDetails = new HashMap<>();
            envDetails.put("activeProfiles", Arrays.toString(environment.getActiveProfiles()));
            envDetails.put("defaultProfiles", Arrays.toString(environment.getDefaultProfiles()));

            builder.withDetail("environment", envDetails);
        };
    }
}

指标端点

java 复制代码
@Service
public class MetricsService {

    @Autowired
    private MeterRegistry meterRegistry;

    // 计数器
    private final Counter requestCounter = Counter.builder("http_requests_total")
            .description("Total number of HTTP requests")
            .tags("method", "GET")
            .register(meterRegistry);

    // 计时器
    private final Timer requestTimer = Timer.builder("http_request_duration")
            .description("HTTP request duration")
            .tags("method", "GET")
            .register(meterRegistry);

    // 仪表
    private final Gauge activeUsers = Gauge.builder("active_users", this, MetricsService::getActiveUsers)
            .description("Number of active users")
            .register(meterRegistry);

    public void recordRequest() {
        requestCounter.increment();
    }

    public void recordRequestDuration(long duration) {
        requestTimer.record(Duration.ofMillis(duration));
    }

    private double getActiveUsers() {
        // 获取活跃用户数的逻辑
        return 42.0;
    }
}

// HTTP请求指标
@Configuration
public class HttpMetricsConfig {

    @Bean
    public TimedAspect timedAspect(MeterRegistry meterRegistry) {
        return new TimedAspect(meterRegistry);
    }
}

@RestController
public class SampleController {

    @Autowired
    private MetricsService metricsService;

    @GetMapping("/api/data")
    @Timed(value = "api.data.requests", description = "Time taken to process data requests")
    public String getData() {
        long startTime = System.currentTimeMillis();

        // 记录请求
        metricsService.recordRequest();

        try {
            // 模拟处理时间
            Thread.sleep(100);
            return "Data response";
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            return "Error";
        } finally {
            // 记录请求持续时间
            long duration = System.currentTimeMillis() - startTime;
            metricsService.recordRequestDuration(duration);
        }
    }
}

配置属性端点

java 复制代码
@Configuration
public class ConfigPropsConfig {

    @Bean
    public ConfigPropsEndpoint configPropsEndpoint(Collection<ConfigurationPropertiesBean> configPropsBeans) {
        return new ConfigPropsEndpoint(configPropsBeans);
    }
}

// 自定义配置属性
@ConfigurationProperties(prefix = "app.custom")
public class CustomProperties {

    private String name;
    private int value;
    private List<String> items;

    // getters and setters
}

// 端点过滤器
@Configuration
public class EndpointFilterConfig {

    @Bean
    public EndpointFilter<ConfigPropsEndpoint> configPropsFilter() {
        return new EndpointFilter<ConfigPropsEndpoint>() {
            @Override
            public ConfigPropsEndpoint filter(ConfigPropsEndpoint endpoint) {
                // 过滤敏感配置信息
                return endpoint;
            }
        };
    }
}

日志端点

java 复制代码
@Configuration
public class LoggingConfig {

    @Bean
    public LoggingEndpoint loggingEndpoint() {
        return new LoggingEndpoint();
    }
}

// 动态日志级别配置
@RestController
@RequestMapping("/actuator/logging")
public class LoggingController {

    @Autowired
    private LoggingSystem loggingSystem;

    @PostMapping("/level")
    public void setLogLevel(@RequestParam String logger, @RequestParam String level) {
        loggingSystem.setLogLevel(logger, LogLevel.valueOf(level.toUpperCase()));
    }

    @GetMapping("/level")
    public Map<String, Object> getLogLevel(@RequestParam String logger) {
        Map<String, Object> result = new HashMap<>();
        result.put("logger", logger);
        result.put("level", loggingSystem.getLoggerConfiguration(logger));
        return result;
    }
}

自定义端点

基础自定义端点

java 复制代码
@Component
@Endpoint(id = "custom")
public class CustomEndpoint {

    @ReadOperation
    public Map<String, Object> custom() {
        Map<String, Object> result = new HashMap<>();
        result.put("message", "Custom endpoint response");
        result.put("timestamp", System.currentTimeMillis());
        return result;
    }

    @ReadOperation
    public Map<String, Object> customWithParam(@Selector String param) {
        Map<String, Object> result = new HashMap<>();
        result.put("param", param);
        result.put("processed", "Processed: " + param);
        return result;
    }

    @WriteOperation
    public Map<String, Object> updateCustom(@Selector String param, @RequestBody Map<String, Object> body) {
        Map<String, Object> result = new HashMap<>();
        result.put("action", "update");
        result.put("param", param);
        result.put("body", body);
        return result;
    }

    @DeleteOperation
    public Map<String, Object> deleteCustom(@Selector String param) {
        Map<String, Object> result = new HashMap<>();
        result.put("action", "delete");
        result.put("param", param);
        return result;
    }
}

// 带Web扩展的自定义端点
@Component
@WebEndpoint(id = "advanced-custom")
public class AdvancedCustomEndpoint {

    @GetMapping("/details")
    @ReadOperation
    public WebEndpointResponse<Map<String, Object>> getDetails() {
        Map<String, Object> details = new HashMap<>();
        details.put("version", "1.0.0");
        details.put("status", "active");

        return new WebEndpointResponse<>(details, 200);
    }

    @PostMapping("/action")
    @WriteOperation
    public WebEndpointResponse<String> performAction(@RequestBody Map<String, Object> action) {
        // 执行操作逻辑
        return new WebEndpointResponse<>("Action performed successfully", 200);
    }
}

业务指标端点

java 复制代码
@Component
@Endpoint(id = "business-metrics")
public class BusinessMetricsEndpoint {

    @Autowired
    private MeterRegistry meterRegistry;

    @ReadOperation
    public Map<String, Object> businessMetrics() {
        Map<String, Object> metrics = new HashMap<>();

        // 获取业务指标
        Counter orderCounter = meterRegistry.find("orders.total").counter();
        if (orderCounter != null) {
            metrics.put("totalOrders", orderCounter.count());
        }

        Timer orderTimer = meterRegistry.find("orders.processing.time").timer();
        if (orderTimer != null) {
            metrics.put("averageOrderProcessingTime", orderTimer.mean(Duration.ofMillis(1)));
        }

        Gauge activeSessions = meterRegistry.find("sessions.active").gauge();
        if (activeSessions != null) {
            metrics.put("activeSessions", activeSessions.value());
        }

        return metrics;
    }

    @ReadOperation
    public Map<String, Object> businessMetricsByType(@Selector String type) {
        Map<String, Object> metrics = new HashMap<>();
        metrics.put("type", type);

        switch (type.toLowerCase()) {
            case "orders":
                metrics.putAll(getOrderMetrics());
                break;
            case "users":
                metrics.putAll(getUserMetrics());
                break;
            case "revenue":
                metrics.putAll(getRevenueMetrics());
                break;
            default:
                metrics.put("error", "Unknown metric type: " + type);
        }

        return metrics;
    }

    private Map<String, Object> getOrderMetrics() {
        Map<String, Object> metrics = new HashMap<>();
        // 获取订单相关指标
        return metrics;
    }

    private Map<String, Object> getUserMetrics() {
        Map<String, Object> metrics = new HashMap<>();
        // 获取用户相关指标
        return metrics;
    }

    private Map<String, Object> getRevenueMetrics() {
        Map<String, Object> metrics = new HashMap<>();
        // 获取收入相关指标
        return metrics;
    }
}

缓存端点

java 复制代码
@Component
@Endpoint(id = "cache")
public class CacheEndpoint {

    @Autowired
    private CacheManager cacheManager;

    @ReadOperation
    public Map<String, Object> cacheInfo() {
        Map<String, Object> result = new HashMap<>();

        for (String cacheName : cacheManager.getCacheNames()) {
            Cache cache = cacheManager.getCache(cacheName);
            Map<String, Object> cacheInfo = new HashMap<>();
            cacheInfo.put("name", cacheName);
            cacheInfo.put("nativeCache", cache.getNativeCache().getClass().getSimpleName());

            // 如果是Caffeine缓存,获取更多信息
            if (cache.getNativeCache() instanceof com.github.benmanes.caffeine.cache.Cache) {
                com.github.benmanes.caffeine.cache.Cache nativeCache =
                    (com.github.benmanes.caffeine.cache.Cache) cache.getNativeCache();
                cacheInfo.put("estimatedSize", nativeCache.estimatedSize());
            }

            result.put(cacheName, cacheInfo);
        }

        return result;
    }

    @WriteOperation
    public Map<String, Object> clearCache(@Selector String cacheName) {
        Cache cache = cacheManager.getCache(cacheName);
        if (cache != null) {
            cache.clear();
            return Map.of("message", "Cache '" + cacheName + "' cleared successfully");
        } else {
            return Map.of("error", "Cache '" + cacheName + "' not found");
        }
    }

    @ReadOperation
    public Map<String, Object> cacheStats(@Selector String cacheName) {
        Map<String, Object> stats = new HashMap<>();

        Cache cache = cacheManager.getCache(cacheName);
        if (cache != null && cache.getNativeCache() instanceof com.github.benmanes.caffeine.cache.Cache) {
            com.github.benmanes.caffeine.cache.Cache nativeCache =
                (com.github.benmanes.caffeine.cache.Cache) cache.getNativeCache();

            stats.put("cacheName", cacheName);
            stats.put("estimatedSize", nativeCache.estimatedSize());
            // 可以添加更多统计信息
        } else {
            stats.put("error", "Cache statistics not available for '" + cacheName + "'");
        }

        return stats;
    }
}

安全配置

基本安全配置

java 复制代码
@Configuration
@EnableWebSecurity
public class ActuatorSecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .authorizeRequests()
                // 允许公开访问健康检查端点
                .antMatchers("/actuator/health").permitAll()
                // 允许公开访问应用信息端点
                .antMatchers("/actuator/info").permitAll()
                // 其他Actuator端点需要认证
                .antMatchers("/actuator/**").hasRole("ADMIN")
                .anyRequest().authenticated()
            .and()
            .httpBasic(); // 使用HTTP Basic认证
    }

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        auth
            .inMemoryAuthentication()
                .withUser("admin")
                .password("{noop}admin123")
                .roles("ADMIN");
    }
}

// 基于角色的访问控制
@Configuration
public class RoleBasedSecurityConfig {

    @Bean
    public SecurityWebFilterChain securityWebFilterChain(ServerHttpSecurity http) {
        return http
            .authorizeExchange()
                .pathMatchers("/actuator/health/**").permitAll()
                .pathMatchers("/actuator/info/**").permitAll()
                .pathMatchers("/actuator/metrics/**").hasRole("MONITOR")
                .pathMatchers("/actuator/**").hasRole("ADMIN")
                .anyExchange().authenticated()
            .and()
            .httpBasic()
            .and()
            .build();
    }
}

端点访问控制

java 复制代码
@Configuration
public class EndpointAccessConfig {

    @Bean
    public EndpointRequest.EndpointRequestMatcher endpointRequestMatcher() {
        return EndpointRequest.toAnyEndpoint();
    }

    @Bean
    public SecurityEvaluationContextExtension securityEvaluationContextExtension() {
        return new SecurityEvaluationContextExtension();
    }
}

// 自定义端点访问决策
@Component
public class CustomEndpointAccessDecisionVoter implements AccessDecisionVoter<FilterInvocation> {

    @Override
    public boolean supports(ConfigAttribute attribute) {
        return attribute instanceof SecurityConfig &&
               ("ROLE_ADMIN".equals(attribute.getAttribute()) ||
                "ROLE_MONITOR".equals(attribute.getAttribute()));
    }

    @Override
    public boolean supports(Class<?> clazz) {
        return FilterInvocation.class.isAssignableFrom(clazz);
    }

    @Override
    public int vote(Authentication authentication, FilterInvocation object,
                   Collection<ConfigAttribute> attributes) {

        if (authentication == null) {
            return ACCESS_DENIED;
        }

        // 检查用户是否有访问端点的权限
        for (ConfigAttribute attribute : attributes) {
            if (this.supports(attribute)) {
                String requiredRole = attribute.getAttribute();

                for (GrantedAuthority authority : authentication.getAuthorities()) {
                    if (requiredRole.equals(authority.getAuthority())) {
                        return ACCESS_GRANTED;
                    }
                }
            }
        }

        return ACCESS_DENIED;
    }
}

监控集成

java 复制代码
Prometheus集成
management:
  metrics:
    export:
      prometheus:
        enabled: true
  endpoints:
    web:
      exposure:
        include: health,info,metrics,prometheus
java 复制代码
@Configuration
public class PrometheusConfig {

    @Bean
    public MeterRegistryCustomizer<MeterRegistry> metricsCommonTags() {
        return registry -> registry.config()
                .commonTags("application", "my-app")
                .commonTags("instance", getInstanceId());
    }

    @Bean
    public PrometheusMeterRegistry prometheusMeterRegistry(PrometheusConfig config) {
        return new PrometheusMeterRegistry(config);
    }

    private String getInstanceId() {
        // 获取实例ID的逻辑
        return "instance-1";
    }
}

// 自定义Prometheus指标
@Service
public class PrometheusMetricsService {

    @Autowired
    private MeterRegistry meterRegistry;

    public void recordBusinessMetric(String name, double value, String... tags) {
        Gauge.builder(name, () -> value)
                .description("Business metric: " + name)
                .tags(tags)
                .register(meterRegistry);
    }

    public void incrementCounter(String name, String... tags) {
        Counter.builder(name)
                .description("Counter: " + name)
                .tags(tags)
                .register(meterRegistry)
                .increment();
    }

    public void recordTimer(String name, Duration duration, String... tags) {
        Timer.builder(name)
                .description("Timer: " + name)
                .tags(tags)
                .register(meterRegistry)
                .record(duration);
    }
}

Grafana集成

java 复制代码
@Configuration
public class GrafanaConfig {

    @Bean
    public MeterRegistryCustomizer<MeterRegistry> grafanaMetrics() {
        return registry -> registry.config()
                .commonTags("service", "my-service")
                .commonTags("environment", "production");
    }
}

// Grafana仪表板配置
@Component
@Endpoint(id = "grafana")
public class GrafanaEndpoint {

    @ReadOperation
    public Map<String, Object> getDashboardConfig() {
        Map<String, Object> dashboard = new HashMap<>();

        dashboard.put("title", "Application Metrics Dashboard");
        dashboard.put("description", "Spring Boot Actuator Metrics Dashboard");

        List<Map<String, Object>> panels = new ArrayList<>();

        // JVM内存面板
        Map<String, Object> jvmMemoryPanel = new HashMap<>();
        jvmMemoryPanel.put("title", "JVM Memory");
        jvmMemoryPanel.put("type", "graph");
        jvmMemoryPanel.put("targets", Arrays.asList(
            Map.of("expr", "jvm_memory_used_bytes{area=\"heap\"}", "legendFormat", "Heap Used"),
            Map.of("expr", "jvm_memory_used_bytes{area=\"nonheap\"}", "legendFormat", "Non-Heap Used")
        ));
        panels.add(jvmMemoryPanel);

        // HTTP请求面板
        Map<String, Object> httpRequestsPanel = new HashMap<>();
        httpRequestsPanel.put("title", "HTTP Requests");
        httpRequestsPanel.put("type", "graph");
        httpRequestsPanel.put("targets", Arrays.asList(
            Map.of("expr", "http_server_requests_seconds_count", "legendFormat", "Total Requests"),
            Map.of("expr", "http_server_requests_seconds_sum", "legendFormat", "Request Duration")
        ));
        panels.add(httpRequestsPanel);

        dashboard.put("panels", panels);

        return dashboard;
    }
}

生产环境配置

端点分组

java 复制代码
management:
  endpoints:
    web:
      exposure:
        include: health,info,metrics,env,configprops
        exclude: shutdown,heapdump
      base-path: /management

  endpoint:
    health:
      show-details: when-authorized
      probes:
        enabled: true

    metrics:
      enabled: true

    env:
      show-values: when-authorized

  group:
    # 监控组 - 只读端点
    monitor:
      include: health,info,metrics
    # 管理组 - 包含写操作端点
    admin:
      include: "*"
      exclude: heapdump

健康探测

java 复制代码
@Configuration
public class HealthProbesConfig {

    @Bean
    public HealthIndicator livenessIndicator() {
        return () -> Health.up()
                .withDetail("liveness", "Application is alive")
                .build();
    }

    @Bean
    public HealthIndicator readinessIndicator() {
        return () -> {
            // 检查应用是否准备好接收流量
            boolean ready = checkReadiness();

            if (ready) {
                return Health.up()
                        .withDetail("readiness", "Application is ready")
                        .build();
            } else {
                return Health.down()
                        .withDetail("readiness", "Application is not ready")
                        .build();
            }
        };
    }

    private boolean checkReadiness() {
        // 检查数据库连接、外部服务等
        return true;
    }
}

性能监控

java 复制代码
@Configuration
public class PerformanceMonitoringConfig {

    @Bean
    public MeterRegistryCustomizer<MeterRegistry> performanceMetrics() {
        return registry -> registry.config()
                .meterFilter(MeterFilter.denyNameStartsWith("jvm"))
                .meterFilter(MeterFilter.denyNameStartsWith("system"))
                .meterFilter(MeterFilter.maximumAllowableMetrics(1000))
                .meterFilter(MeterFilter.maximumAllowableTags("method", "uri", 100));
    }

    @Bean
    public TimedAspect timedAspect(MeterRegistry meterRegistry) {
        return new TimedAspect(meterRegistry,
                new TimedAspectConfig()
                        .setEnabled(true)
                        .setAutoTimeRequests(true)
                        .setPercentiles(new double[]{0.5, 0.95, 0.99}));
    }
}

故障排查

常见问题

1、端点无法访问

检查端点是否已暴露

验证安全配置

确认Base Path配置

2、指标数据不准确

检查MeterRegistry配置

验证指标命名规范

确认时间单位设置

3、健康检查失败

检查依赖服务的状态

验证数据库连接

查看应用日志

4、性能问题

监控端点响应时间

检查指标收集频率

优化端点暴露策略

调试配置

java 复制代码
@Configuration
public class DebugConfig {

    @Bean
    public ApplicationEventListener<ContextRefreshedEvent> debugListener() {
        return event -> {
            ApplicationContext context = event.getApplicationContext();

            // 打印所有端点信息
            Map<String, Object> endpoints = context.getBeansWithAnnotation(Endpoint.class);
            System.out.println("Available Endpoints:");
            endpoints.forEach((name, bean) -> {
                Endpoint endpoint = bean.getClass().getAnnotation(Endpoint.class);
                System.out.println("- " + endpoint.id() + ": " + bean.getClass().getSimpleName());
            });
        };
    }
}

// 端点访问日志
@Configuration
public class EndpointLoggingConfig {

    @Bean
    public FilterRegistrationBean<EndpointLoggingFilter> endpointLoggingFilter() {
        FilterRegistrationBean<EndpointLoggingFilter> registrationBean = new FilterRegistrationBean<>();
        registrationBean.setFilter(new EndpointLoggingFilter());
        registrationBean.addUrlPatterns("/actuator/*");
        return registrationBean;
    }
}

public class EndpointLoggingFilter implements Filter {

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {

        HttpServletRequest httpRequest = (HttpServletRequest) request;
        HttpServletResponse httpResponse = (HttpServletResponse) response;

        long startTime = System.currentTimeMillis();

        try {
            chain.doFilter(request, response);
        } finally {
            long duration = System.currentTimeMillis() - startTime;
            System.out.println("Endpoint " + httpRequest.getRequestURI() +
                    " took " + duration + "ms, status: " + httpResponse.getStatus());
        }
    }
}

最佳实践

1. 端点管理

根据环境选择合适的端点暴露策略

使用端点分组提高安全性

定期检查端点状态

2. 安全配置

实施最小权限原则

使用HTTPS保护端点通信

定期轮换认证凭据

3. 监控策略

定义关键指标和告警阈值

建立监控仪表板

实施自动化监控

4. 性能优化

控制指标收集频率

使用异步端点处理

实施缓存策略

5. 运维集成

与现有监控系统集成

建立自动化部署流程

实施日志聚合和分析

相关推荐
BlockChain88819 小时前
SpringBoot实战一:10分钟搭建企业级用户管理系统(20000字完整项目)
java·spring boot·后端
leiming619 小时前
linux 进程学习之信号
linux·运维·学习
拽着尾巴的鱼儿19 小时前
Springboot 缓存@Cacheable 使用
spring boot·后端·缓存
被遗忘的旋律.19 小时前
Linux驱动开发笔记(二十四)——(上)IIO + icm20608驱动
linux·驱动开发·笔记
zhangrelay19 小时前
thinkpad等笔记本电脑在ubuntu等linux系统下电池校准如何做?
笔记·学习
_Kayo_19 小时前
Node.JS 学习笔记8
笔记·学习·node.js
weixin_4624462319 小时前
使用 Docker / Docker Compose 部署 PdfDing —— 个人 PDF笔记
笔记·docker·pdf
知识分享小能手19 小时前
Oracle 19c入门学习教程,从入门到精通,Oracle 数据表对象 —— 语法知识点详解与案例实践(10)
数据库·学习·oracle
麦兜*19 小时前
SpringBoot Profile多环境配置详解,一套配置应对所有场景
java·数据库·spring boot
炽烈小老头19 小时前
【每天学习一点算法 2026/01/22】杨辉三角
学习·算法