8.1 JVM性能调优

JVM参数配置

# 生产环境JVM参数示例
java -server \
  -Xms2g -Xmx2g \
  -XX:NewRatio=3 \
  -XX:SurvivorRatio=8 \
  -XX:MetaspaceSize=256m \
  -XX:MaxMetaspaceSize=512m \
  -XX:+UseG1GC \
  -XX:MaxGCPauseMillis=200 \
  -XX:G1HeapRegionSize=16m \
  -XX:+UseStringDeduplication \
  -XX:+PrintGC \
  -XX:+PrintGCDetails \
  -XX:+PrintGCTimeStamps \
  -XX:+PrintGCApplicationStoppedTime \
  -Xloggc:/app/logs/gc.log \
  -XX:+UseGCLogFileRotation \
  -XX:NumberOfGCLogFiles=5 \
  -XX:GCLogFileSize=100M \
  -XX:+HeapDumpOnOutOfMemoryError \
  -XX:HeapDumpPath=/app/logs/heapdump.hprof \
  -Djava.awt.headless=true \
  -Dfile.encoding=UTF-8 \
  -Duser.timezone=Asia/Shanghai \
  -jar myapp.jar

GC调优配置类

@Component
@ConfigurationProperties(prefix = "app.jvm")
@Data
public class JvmConfig {
    
    private Memory memory = new Memory();
    private Gc gc = new Gc();
    private Monitoring monitoring = new Monitoring();
    
    @Data
    public static class Memory {
        private String heapSize = "2g";
        private String newRatio = "3";
        private String survivorRatio = "8";
        private String metaspaceSize = "256m";
        private String maxMetaspaceSize = "512m";
    }
    
    @Data
    public static class Gc {
        private String collector = "G1GC";
        private int maxPauseMillis = 200;
        private String regionSize = "16m";
        private boolean stringDeduplication = true;
        private boolean printGcDetails = true;
    }
    
    @Data
    public static class Monitoring {
        private boolean heapDumpOnOom = true;
        private String heapDumpPath = "/app/logs/heapdump.hprof";
        private String gcLogPath = "/app/logs/gc.log";
        private int gcLogFiles = 5;
        private String gcLogFileSize = "100M";
    }
}

@Component
public class JvmMonitor {
    
    private final MemoryMXBean memoryBean;
    private final List<GarbageCollectorMXBean> gcBeans;
    private final ThreadMXBean threadBean;
    
    public JvmMonitor() {
        this.memoryBean = ManagementFactory.getMemoryMXBean();
        this.gcBeans = ManagementFactory.getGarbageCollectorMXBeans();
        this.threadBean = ManagementFactory.getThreadMXBean();
    }
    
    @EventListener
    @Async
    public void handleContextRefresh(ContextRefreshedEvent event) {
        logJvmInfo();
        startPeriodicMonitoring();
    }
    
    private void logJvmInfo() {
        RuntimeMXBean runtimeBean = ManagementFactory.getRuntimeMXBean();
        log.info("JVM启动参数: {}", runtimeBean.getInputArguments());
        log.info("JVM版本: {}", runtimeBean.getVmVersion());
        log.info("可用处理器: {}", Runtime.getRuntime().availableProcessors());
    }
    
    @Scheduled(fixedRate = 60000) // 每分钟检查一次
    public void monitorMemory() {
        MemoryUsage heapUsage = memoryBean.getHeapMemoryUsage();
        MemoryUsage nonHeapUsage = memoryBean.getNonHeapMemoryUsage();
        
        double heapUsedPercent = (double) heapUsage.getUsed() / heapUsage.getMax() * 100;
        double nonHeapUsedPercent = (double) nonHeapUsage.getUsed() / nonHeapUsage.getMax() * 100;
        
        log.debug("堆内存使用率: {:.2f}%, 非堆内存使用率: {:.2f}%", 
                 heapUsedPercent, nonHeapUsedPercent);
        
        // 内存使用率告警
        if (heapUsedPercent > 80) {
            log.warn("堆内存使用率过高: {:.2f}%", heapUsedPercent);
        }
        
        if (nonHeapUsedPercent > 90) {
            log.warn("非堆内存使用率过高: {:.2f}%", nonHeapUsedPercent);
        }
    }
    
    @Scheduled(fixedRate = 300000) // 每5分钟检查一次
    public void monitorGc() {
        for (GarbageCollectorMXBean gcBean : gcBeans) {
            long collections = gcBean.getCollectionCount();
            long time = gcBean.getCollectionTime();
            
            if (collections > 0) {
                double avgTime = (double) time / collections;
                log.debug("GC统计 - {}: 次数={}, 总时间={}ms, 平均时间={:.2f}ms", 
                         gcBean.getName(), collections, time, avgTime);
                
                // GC时间告警
                if (avgTime > 100) {
                    log.warn("GC平均时间过长: {:.2f}ms", avgTime);
                }
            }
        }
    }
    
    @Scheduled(fixedRate = 120000) // 每2分钟检查一次
    public void monitorThreads() {
        int threadCount = threadBean.getThreadCount();
        int peakThreadCount = threadBean.getPeakThreadCount();
        
        log.debug("线程统计 - 当前: {}, 峰值: {}", threadCount, peakThreadCount);
        
        // 线程数告警
        if (threadCount > 500) {
            log.warn("线程数过多: {}", threadCount);
        }
    }
    
    private void startPeriodicMonitoring() {
        // 启动定期监控任务
        log.info("JVM监控已启动");
    }
}

8.2 数据库性能优化

连接池优化

# application.yml
spring:
  datasource:
    hikari:
      # 连接池配置
      minimum-idle: 10
      maximum-pool-size: 50
      idle-timeout: 300000
      max-lifetime: 1800000
      connection-timeout: 30000
      validation-timeout: 5000
      
      # 连接测试
      connection-test-query: SELECT 1
      test-while-idle: true
      test-on-borrow: false
      test-on-return: false
      
      # 性能配置
      auto-commit: true
      read-only: false
      isolation-level: TRANSACTION_READ_COMMITTED
      
      # 监控配置
      register-mbeans: true
      
      # 连接属性
      data-source-properties:
        cachePrepStmts: true
        prepStmtCacheSize: 250
        prepStmtCacheSqlLimit: 2048
        useServerPrepStmts: true
        useLocalSessionState: true
        rewriteBatchedStatements: true
        cacheResultSetMetadata: true
        cacheServerConfiguration: true
        elideSetAutoCommits: true
        maintainTimeStats: false

  jpa:
    hibernate:
      ddl-auto: none
    properties:
      hibernate:
        # 查询优化
        jdbc:
          batch_size: 50
          fetch_size: 50
        
        # 缓存配置
        cache:
          use_second_level_cache: true
          use_query_cache: true
          region:
            factory_class: org.hibernate.cache.jcache.JCacheRegionFactory
        
        # SQL优化
        show_sql: false
        format_sql: false
        use_sql_comments: false
        
        # 统计信息
        generate_statistics: true
        
        # 连接释放模式
        connection:
          release_mode: after_transaction

查询优化服务

@Service
@Transactional(readOnly = true)
public class QueryOptimizationService {
    
    @Autowired
    private EntityManager entityManager;
    
    @Autowired
    private JdbcTemplate jdbcTemplate;
    
    /**
     * 批量查询优化
     */
    public List<User> findUsersByIdsOptimized(List<Long> userIds) {
        if (userIds.isEmpty()) {
            return Collections.emptyList();
        }
        
        // 使用IN查询替代多次单独查询
        String jpql = "SELECT u FROM User u WHERE u.id IN :ids";
        return entityManager.createQuery(jpql, User.class)
                .setParameter("ids", userIds)
                .getResultList();
    }
    
    /**
     * 分页查询优化
     */
    public Page<User> findUsersOptimized(Pageable pageable, UserSearchCriteria criteria) {
        // 构建动态查询
        CriteriaBuilder cb = entityManager.getCriteriaBuilder();
        CriteriaQuery<User> query = cb.createQuery(User.class);
        Root<User> root = query.from(User.class);
        
        List<Predicate> predicates = new ArrayList<>();
        
        // 添加查询条件
        if (StringUtils.hasText(criteria.getName())) {
            predicates.add(cb.like(root.get("name"), "%" + criteria.getName() + "%"));
        }
        
        if (criteria.getStatus() != null) {
            predicates.add(cb.equal(root.get("status"), criteria.getStatus()));
        }
        
        if (criteria.getCreateTimeStart() != null) {
            predicates.add(cb.greaterThanOrEqualTo(root.get("createTime"), criteria.getCreateTimeStart()));
        }
        
        if (criteria.getCreateTimeEnd() != null) {
            predicates.add(cb.lessThanOrEqualTo(root.get("createTime"), criteria.getCreateTimeEnd()));
        }
        
        query.where(predicates.toArray(new Predicate[0]));
        
        // 添加排序
        if (pageable.getSort().isSorted()) {
            List<Order> orders = new ArrayList<>();
            for (Sort.Order sortOrder : pageable.getSort()) {
                if (sortOrder.isAscending()) {
                    orders.add(cb.asc(root.get(sortOrder.getProperty())));
                } else {
                    orders.add(cb.desc(root.get(sortOrder.getProperty())));
                }
            }
            query.orderBy(orders);
        }
        
        // 执行查询
        TypedQuery<User> typedQuery = entityManager.createQuery(query);
        typedQuery.setFirstResult((int) pageable.getOffset());
        typedQuery.setMaxResults(pageable.getPageSize());
        
        List<User> users = typedQuery.getResultList();
        
        // 计算总数(优化:只在需要时计算)
        long total = countUsersOptimized(criteria);
        
        return new PageImpl<>(users, pageable, total);
    }
    
    /**
     * 计数查询优化
     */
    private long countUsersOptimized(UserSearchCriteria criteria) {
        CriteriaBuilder cb = entityManager.getCriteriaBuilder();
        CriteriaQuery<Long> countQuery = cb.createQuery(Long.class);
        Root<User> root = countQuery.from(User.class);
        
        countQuery.select(cb.count(root));
        
        // 重用查询条件逻辑
        List<Predicate> predicates = buildPredicates(cb, root, criteria);
        countQuery.where(predicates.toArray(new Predicate[0]));
        
        return entityManager.createQuery(countQuery).getSingleResult();
    }
    
    /**
     * N+1查询问题解决
     */
    public List<User> findUsersWithRolesOptimized() {
        // 使用JOIN FETCH避免N+1问题
        String jpql = "SELECT DISTINCT u FROM User u LEFT JOIN FETCH u.roles";
        return entityManager.createQuery(jpql, User.class).getResultList();
    }
    
    /**
     * 原生SQL查询优化
     */
    public List<UserStatistics> getUserStatistics(LocalDate startDate, LocalDate endDate) {
        String sql = """
            SELECT 
                DATE(u.create_time) as date,
                COUNT(*) as user_count,
                COUNT(CASE WHEN u.status = 'ACTIVE' THEN 1 END) as active_count
            FROM users u 
            WHERE u.create_time BETWEEN ? AND ?
            GROUP BY DATE(u.create_time)
            ORDER BY date
            """;
        
        return jdbcTemplate.query(sql, 
            (rs, rowNum) -> UserStatistics.builder()
                .date(rs.getDate("date").toLocalDate())
                .userCount(rs.getLong("user_count"))
                .activeCount(rs.getLong("active_count"))
                .build(),
            startDate, endDate);
    }
    
    /**
     * 批量操作优化
     */
    @Transactional
    public void batchUpdateUserStatus(List<Long> userIds, UserStatus status) {
        String jpql = "UPDATE User u SET u.status = :status, u.updateTime = :updateTime WHERE u.id IN :ids";
        
        int batchSize = 1000;
        for (int i = 0; i < userIds.size(); i += batchSize) {
            List<Long> batch = userIds.subList(i, Math.min(i + batchSize, userIds.size()));
            
            entityManager.createQuery(jpql)
                .setParameter("status", status)
                .setParameter("updateTime", LocalDateTime.now())
                .setParameter("ids", batch)
                .executeUpdate();
        }
    }
    
    private List<Predicate> buildPredicates(CriteriaBuilder cb, Root<User> root, UserSearchCriteria criteria) {
        List<Predicate> predicates = new ArrayList<>();
        
        if (StringUtils.hasText(criteria.getName())) {
            predicates.add(cb.like(root.get("name"), "%" + criteria.getName() + "%"));
        }
        
        if (criteria.getStatus() != null) {
            predicates.add(cb.equal(root.get("status"), criteria.getStatus()));
        }
        
        if (criteria.getCreateTimeStart() != null) {
            predicates.add(cb.greaterThanOrEqualTo(root.get("createTime"), criteria.getCreateTimeStart()));
        }
        
        if (criteria.getCreateTimeEnd() != null) {
            predicates.add(cb.lessThanOrEqualTo(root.get("createTime"), criteria.getCreateTimeEnd()));
        }
        
        return predicates;
    }
}

@Data
@Builder
public class UserStatistics {
    private LocalDate date;
    private Long userCount;
    private Long activeCount;
}

@Data
public class UserSearchCriteria {
    private String name;
    private UserStatus status;
    private LocalDateTime createTimeStart;
    private LocalDateTime createTimeEnd;
}

8.3 缓存优化

多级缓存配置

@Configuration
@EnableCaching
public class CacheConfig {
    
    @Bean
    @Primary
    public CacheManager cacheManager() {
        CompositeCacheManager compositeCacheManager = new CompositeCacheManager();
        
        // L1缓存:本地缓存(Caffeine)
        CaffeineCacheManager caffeineCacheManager = new CaffeineCacheManager();
        caffeineCacheManager.setCaffeine(Caffeine.newBuilder()
            .maximumSize(1000)
            .expireAfterWrite(Duration.ofMinutes(10))
            .recordStats());
        
        // L2缓存:分布式缓存(Redis)
        RedisCacheManager redisCacheManager = RedisCacheManager.builder(redisConnectionFactory())
            .cacheDefaults(redisCacheConfiguration())
            .build();
        
        compositeCacheManager.setCacheManagers(Arrays.asList(
            caffeineCacheManager, 
            redisCacheManager
        ));
        
        compositeCacheManager.setFallbackToNoOpCache(false);
        return compositeCacheManager;
    }
    
    @Bean
    public RedisCacheConfiguration redisCacheConfiguration() {
        return RedisCacheConfiguration.defaultCacheConfig()
            .entryTtl(Duration.ofHours(1))
            .serializeKeysWith(RedisSerializationContext.SerializationPair
                .fromSerializer(new StringRedisSerializer()))
            .serializeValuesWith(RedisSerializationContext.SerializationPair
                .fromSerializer(new GenericJackson2JsonRedisSerializer()))
            .disableCachingNullValues();
    }
    
    @Bean
    public RedisConnectionFactory redisConnectionFactory() {
        LettuceConnectionFactory factory = new LettuceConnectionFactory(
            new RedisStandaloneConfiguration("localhost", 6379));
        factory.setValidateConnection(true);
        return factory;
    }
}

@Service
public class CacheOptimizationService {
    
    @Autowired
    private UserRepository userRepository;
    
    @Autowired
    private CacheManager cacheManager;
    
    /**
     * 缓存穿透防护
     */
    @Cacheable(value = "users", key = "#id", unless = "#result == null")
    public Optional<User> findUserById(Long id) {
        if (id == null || id <= 0) {
            return Optional.empty();
        }
        
        return userRepository.findById(id);
    }
    
    /**
     * 缓存雪崩防护(随机TTL)
     */
    @Cacheable(value = "user-list", key = "#criteria.hashCode()")
    public List<User> findUsersByCriteria(UserSearchCriteria criteria) {
        // 添加随机延迟,防止缓存雪崩
        String cacheKey = "user-list::" + criteria.hashCode();
        Cache cache = cacheManager.getCache("user-list");
        
        if (cache != null) {
            // 设置随机TTL(基础TTL + 随机时间)
            long randomTtl = 3600 + new Random().nextInt(600); // 1小时 + 0-10分钟随机
            // 这里需要根据具体缓存实现来设置TTL
        }
        
        return userRepository.findByCriteria(criteria);
    }
    
    /**
     * 缓存击穿防护(分布式锁)
     */
    @Cacheable(value = "hot-data", key = "#key")
    public String getHotData(String key) {
        // 使用分布式锁防止缓存击穿
        String lockKey = "lock:hot-data:" + key;
        
        try {
            // 尝试获取锁
            Boolean lockAcquired = redisTemplate.opsForValue()
                .setIfAbsent(lockKey, "locked", Duration.ofSeconds(10));
            
            if (Boolean.TRUE.equals(lockAcquired)) {
                try {
                    // 双重检查
                    Cache cache = cacheManager.getCache("hot-data");
                    if (cache != null) {
                        Cache.ValueWrapper wrapper = cache.get(key);
                        if (wrapper != null) {
                            return (String) wrapper.get();
                        }
                    }
                    
                    // 从数据库加载数据
                    return loadDataFromDatabase(key);
                } finally {
                    // 释放锁
                    redisTemplate.delete(lockKey);
                }
            } else {
                // 等待其他线程加载完成
                Thread.sleep(100);
                return getHotData(key); // 递归调用
            }
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            throw new RuntimeException("获取热点数据被中断", e);
        }
    }
    
    /**
     * 预热缓存
     */
    @EventListener
    @Async
    public void warmUpCache(ContextRefreshedEvent event) {
        log.info("开始预热缓存...");
        
        // 预热用户缓存
        List<Long> hotUserIds = getHotUserIds();
        for (Long userId : hotUserIds) {
            findUserById(userId);
        }
        
        // 预热配置缓存
        loadSystemConfigurations();
        
        log.info("缓存预热完成");
    }
    
    /**
     * 缓存更新策略
     */
    @CacheEvict(value = "users", key = "#user.id")
    public User updateUser(User user) {
        User updatedUser = userRepository.save(user);
        
        // 异步更新相关缓存
        asyncUpdateRelatedCache(user.getId());
        
        return updatedUser;
    }
    
    @Async
    private void asyncUpdateRelatedCache(Long userId) {
        // 更新用户相关的其他缓存
        cacheManager.getCache("user-roles").evict(userId);
        cacheManager.getCache("user-permissions").evict(userId);
    }
    
    private List<Long> getHotUserIds() {
        // 获取热点用户ID列表
        return Arrays.asList(1L, 2L, 3L, 4L, 5L);
    }
    
    private void loadSystemConfigurations() {
        // 加载系统配置到缓存
    }
    
    private String loadDataFromDatabase(String key) {
        // 从数据库加载数据
        return "data-" + key;
    }
    
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;
}

8.4 异步处理优化

线程池配置

@Configuration
@EnableAsync
public class AsyncConfig implements AsyncConfigurer {
    
    @Bean(name = "taskExecutor")
    public ThreadPoolTaskExecutor taskExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        
        // 核心线程数
        executor.setCorePoolSize(Runtime.getRuntime().availableProcessors());
        
        // 最大线程数
        executor.setMaxPoolSize(Runtime.getRuntime().availableProcessors() * 2);
        
        // 队列容量
        executor.setQueueCapacity(1000);
        
        // 线程名前缀
        executor.setThreadNamePrefix("async-task-");
        
        // 拒绝策略
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        
        // 线程空闲时间
        executor.setKeepAliveSeconds(60);
        
        // 等待任务完成后关闭
        executor.setWaitForTasksToCompleteOnShutdown(true);
        executor.setAwaitTerminationSeconds(30);
        
        executor.initialize();
        return executor;
    }
    
    @Bean(name = "ioTaskExecutor")
    public ThreadPoolTaskExecutor ioTaskExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        
        // IO密集型任务配置更多线程
        executor.setCorePoolSize(Runtime.getRuntime().availableProcessors() * 2);
        executor.setMaxPoolSize(Runtime.getRuntime().availableProcessors() * 4);
        executor.setQueueCapacity(2000);
        executor.setThreadNamePrefix("io-task-");
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        executor.setKeepAliveSeconds(120);
        executor.setWaitForTasksToCompleteOnShutdown(true);
        executor.setAwaitTerminationSeconds(60);
        
        executor.initialize();
        return executor;
    }
    
    @Override
    public Executor getAsyncExecutor() {
        return taskExecutor();
    }
    
    @Override
    public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
        return new CustomAsyncExceptionHandler();
    }
}

@Component
public class CustomAsyncExceptionHandler implements AsyncUncaughtExceptionHandler {
    
    @Override
    public void handleUncaughtException(Throwable ex, Method method, Object... params) {
        log.error("异步任务执行异常 - 方法: {}, 参数: {}", method.getName(), Arrays.toString(params), ex);
        
        // 发送告警通知
        sendAlertNotification(ex, method, params);
    }
    
    private void sendAlertNotification(Throwable ex, Method method, Object... params) {
        // 实现告警通知逻辑
    }
}

@Service
public class AsyncProcessingService {
    
    @Async("taskExecutor")
    public CompletableFuture<String> processDataAsync(String data) {
        try {
            // 模拟数据处理
            Thread.sleep(1000);
            String result = "Processed: " + data;
            log.info("异步处理完成: {}", result);
            return CompletableFuture.completedFuture(result);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            return CompletableFuture.failedFuture(e);
        }
    }
    
    @Async("ioTaskExecutor")
    public CompletableFuture<Void> sendEmailAsync(String to, String subject, String content) {
        try {
            // 模拟邮件发送
            Thread.sleep(2000);
            log.info("邮件发送完成: {} -> {}", subject, to);
            return CompletableFuture.completedFuture(null);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            return CompletableFuture.failedFuture(e);
        }
    }
    
    /**
     * 批量异步处理
     */
    public CompletableFuture<List<String>> batchProcessAsync(List<String> dataList) {
        List<CompletableFuture<String>> futures = dataList.stream()
            .map(this::processDataAsync)
            .collect(Collectors.toList());
        
        return CompletableFuture.allOf(futures.toArray(new CompletableFuture[0]))
            .thenApply(v -> futures.stream()
                .map(CompletableFuture::join)
                .collect(Collectors.toList()));
    }
    
    /**
     * 异步任务编排
     */
    public CompletableFuture<String> complexAsyncWorkflow(String input) {
        return processDataAsync(input)
            .thenCompose(result -> {
                // 第二步处理
                return CompletableFuture.supplyAsync(() -> {
                    return "Enhanced: " + result;
                });
            })
            .thenCompose(enhanced -> {
                // 第三步处理
                return CompletableFuture.supplyAsync(() -> {
                    return "Final: " + enhanced;
                });
            })
            .exceptionally(ex -> {
                log.error("异步工作流执行失败", ex);
                return "Error: " + ex.getMessage();
            });
    }
}

8.5 HTTP性能优化

连接池配置

@Configuration
public class HttpClientConfig {
    
    @Bean
    public RestTemplate restTemplate() {
        RestTemplate restTemplate = new RestTemplate();
        
        // 配置HTTP连接池
        HttpComponentsClientHttpRequestFactory factory = 
            new HttpComponentsClientHttpRequestFactory();
        
        factory.setHttpClient(httpClient());
        factory.setConnectTimeout(5000);
        factory.setReadTimeout(10000);
        
        restTemplate.setRequestFactory(factory);
        
        // 添加拦截器
        restTemplate.getInterceptors().add(new LoggingInterceptor());
        restTemplate.getInterceptors().add(new RetryInterceptor());
        
        return restTemplate;
    }
    
    @Bean
    public CloseableHttpClient httpClient() {
        return HttpClients.custom()
            .setConnectionManager(poolingConnectionManager())
            .setDefaultRequestConfig(requestConfig())
            .setRetryHandler(new DefaultHttpRequestRetryHandler(3, true))
            .build();
    }
    
    @Bean
    public PoolingHttpClientConnectionManager poolingConnectionManager() {
        PoolingHttpClientConnectionManager manager = new PoolingHttpClientConnectionManager();
        
        // 最大连接数
        manager.setMaxTotal(200);
        
        // 每个路由的最大连接数
        manager.setDefaultMaxPerRoute(50);
        
        // 连接存活时间
        manager.setDefaultSocketConfig(SocketConfig.custom()
            .setSoTimeout(10000)
            .build());
        
        return manager;
    }
    
    @Bean
    public RequestConfig requestConfig() {
        return RequestConfig.custom()
            .setConnectTimeout(5000)
            .setSocketTimeout(10000)
            .setConnectionRequestTimeout(3000)
            .build();
    }
}

@Component
public class LoggingInterceptor implements ClientHttpRequestInterceptor {
    
    @Override
    public ClientHttpResponse intercept(
            HttpRequest request, 
            byte[] body, 
            ClientHttpRequestExecution execution) throws IOException {
        
        long startTime = System.currentTimeMillis();
        
        log.debug("HTTP请求: {} {}", request.getMethod(), request.getURI());
        
        ClientHttpResponse response = execution.execute(request, body);
        
        long duration = System.currentTimeMillis() - startTime;
        log.debug("HTTP响应: {} - {}ms", response.getStatusCode(), duration);
        
        return response;
    }
}

@Component
public class RetryInterceptor implements ClientHttpRequestInterceptor {
    
    private static final int MAX_RETRIES = 3;
    private static final long RETRY_DELAY = 1000;
    
    @Override
    public ClientHttpResponse intercept(
            HttpRequest request, 
            byte[] body, 
            ClientHttpRequestExecution execution) throws IOException {
        
        IOException lastException = null;
        
        for (int i = 0; i < MAX_RETRIES; i++) {
            try {
                return execution.execute(request, body);
            } catch (IOException e) {
                lastException = e;
                
                if (i < MAX_RETRIES - 1) {
                    log.warn("HTTP请求失败,准备重试 ({}/{}): {}", 
                            i + 1, MAX_RETRIES, e.getMessage());
                    
                    try {
                        Thread.sleep(RETRY_DELAY * (i + 1));
                    } catch (InterruptedException ie) {
                        Thread.currentThread().interrupt();
                        throw new IOException("重试被中断", ie);
                    }
                }
            }
        }
        
        throw lastException;
    }
}

响应压缩配置

# application.yml
server:
  compression:
    enabled: true
    mime-types:
      - text/html
      - text/xml
      - text/plain
      - text/css
      - text/javascript
      - application/javascript
      - application/json
      - application/xml
    min-response-size: 1024
  
  http2:
    enabled: true
  
  tomcat:
    max-connections: 8192
    max-threads: 200
    min-spare-threads: 10
    accept-count: 100
    connection-timeout: 20000
    
    # 访问日志
    accesslog:
      enabled: true
      directory: /app/logs
      file-date-format: .yyyy-MM-dd
      pattern: '%h %l %u %t "%r" %s %b %D'
      prefix: access_log
      suffix: .log

8.6 最佳实践总结

性能监控指标

@Component
public class PerformanceMetrics {
    
    private final MeterRegistry meterRegistry;
    private final Timer.Sample sample;
    
    public PerformanceMetrics(MeterRegistry meterRegistry) {
        this.meterRegistry = meterRegistry;
        this.sample = Timer.start(meterRegistry);
    }
    
    /**
     * 记录方法执行时间
     */
    @Around("@annotation(Timed)")
    public Object timeMethod(ProceedingJoinPoint joinPoint) throws Throwable {
        Timer.Sample sample = Timer.start(meterRegistry);
        
        try {
            return joinPoint.proceed();
        } finally {
            sample.stop(Timer.builder("method.execution.time")
                .tag("class", joinPoint.getTarget().getClass().getSimpleName())
                .tag("method", joinPoint.getSignature().getName())
                .register(meterRegistry));
        }
    }
    
    /**
     * 记录数据库查询性能
     */
    public void recordDatabaseQuery(String operation, long duration) {
        Timer.builder("database.query.time")
            .tag("operation", operation)
            .register(meterRegistry)
            .record(duration, TimeUnit.MILLISECONDS);
    }
    
    /**
     * 记录缓存命中率
     */
    public void recordCacheHit(String cacheName, boolean hit) {
        Counter.builder("cache.requests")
            .tag("cache", cacheName)
            .tag("result", hit ? "hit" : "miss")
            .register(meterRegistry)
            .increment();
    }
    
    /**
     * 记录HTTP请求性能
     */
    public void recordHttpRequest(String method, String uri, int status, long duration) {
        Timer.builder("http.requests")
            .tag("method", method)
            .tag("uri", uri)
            .tag("status", String.valueOf(status))
            .register(meterRegistry)
            .record(duration, TimeUnit.MILLISECONDS);
    }
}

@RestController
public class PerformanceController {
    
    @Autowired
    private PerformanceMetrics performanceMetrics;
    
    @GetMapping("/api/performance/metrics")
    public ResponseEntity<Map<String, Object>> getPerformanceMetrics() {
        Map<String, Object> metrics = new HashMap<>();
        
        // JVM指标
        Runtime runtime = Runtime.getRuntime();
        metrics.put("jvm.memory.used", runtime.totalMemory() - runtime.freeMemory());
        metrics.put("jvm.memory.free", runtime.freeMemory());
        metrics.put("jvm.memory.total", runtime.totalMemory());
        metrics.put("jvm.memory.max", runtime.maxMemory());
        
        // 线程指标
        ThreadMXBean threadBean = ManagementFactory.getThreadMXBean();
        metrics.put("threads.count", threadBean.getThreadCount());
        metrics.put("threads.peak", threadBean.getPeakThreadCount());
        
        // GC指标
        List<GarbageCollectorMXBean> gcBeans = ManagementFactory.getGarbageCollectorMXBeans();
        for (GarbageCollectorMXBean gcBean : gcBeans) {
            metrics.put("gc." + gcBean.getName().toLowerCase() + ".collections", gcBean.getCollectionCount());
            metrics.put("gc." + gcBean.getName().toLowerCase() + ".time", gcBean.getCollectionTime());
        }
        
        return ResponseEntity.ok(metrics);
    }
}

性能优化检查清单

## Spring Boot性能优化检查清单

### JVM优化
- [ ] 配置合适的堆内存大小(-Xms, -Xmx)
- [ ] 选择合适的垃圾收集器(G1GC推荐)
- [ ] 配置GC日志和监控
- [ ] 启用JVM性能参数
- [ ] 配置OOM时自动dump堆内存

### 数据库优化
- [ ] 配置连接池参数
- [ ] 优化SQL查询和索引
- [ ] 启用查询缓存
- [ ] 配置批量操作
- [ ] 避免N+1查询问题

### 缓存优化
- [ ] 实现多级缓存策略
- [ ] 防止缓存穿透、击穿、雪崩
- [ ] 配置合理的TTL
- [ ] 实现缓存预热
- [ ] 监控缓存命中率

### 异步处理
- [ ] 配置线程池参数
- [ ] 使用异步处理非关键业务
- [ ] 实现异步任务监控
- [ ] 配置异常处理策略

### HTTP优化
- [ ] 启用响应压缩
- [ ] 配置HTTP/2
- [ ] 优化连接池配置
- [ ] 实现请求重试机制
- [ ] 配置超时参数

### 监控和诊断
- [ ] 集成APM工具
- [ ] 配置性能指标收集
- [ ] 实现健康检查
- [ ] 配置告警规则
- [ ] 定期性能测试

总结

本章详细介绍了Spring Boot应用的性能优化:

  1. JVM性能调优:内存配置、GC优化、监控指标
  2. 数据库性能优化:连接池配置、查询优化、批量操作
  3. 缓存优化:多级缓存、防护策略、预热机制
  4. 异步处理优化:线程池配置、任务编排、异常处理
  5. HTTP性能优化:连接池、压缩、重试机制
  6. 最佳实践:性能监控、优化检查清单

通过这些优化措施,可以显著提升Spring Boot应用的性能和稳定性,为用户提供更好的体验。