Java配置资源优化案例实操

wen java案例 31

本文目录导读:

Java配置资源优化案例实操

  1. 案例背景
  2. 问题分析
  3. 优化方案实操
  4. 性能对比
  5. 监控配置

我来提供一个完整的Java配置资源优化案例实操指南,包含具体场景和优化方案。

案例背景

假设我们有一个电商系统的商品服务,最初配置资源如下:

# 原始配置 (application.properties)
server.port=8080
server.tomcat.max-threads=200
server.tomcat.max-connections=10000
spring.datasource.url=jdbc:mysql://localhost:3306/shop
spring.datasource.hikari.maximum-pool-size=10
spring.datasource.hikari.minimum-idle=5
spring.redis.host=localhost
spring.redis.lettuce.pool.max-active=8
spring.redis.lettuce.pool.max-idle=8
spring.redis.lettuce.pool.min-idle=0

问题分析

系统出现以下问题:

  1. 高并发时响应变慢
  2. 偶尔出现连接池满异常
  3. 数据库连接经常超时

优化方案实操

线程池优化

# 优化后的线程池配置
server.tomcat.threads.max=50  # 根据CPU核心数调整,2C4G建议50-100
server.tomcat.threads.min-spare=10
server.tomcat.max-connections=5000
server.tomcat.accept-count=100
server.tomcat.connection-timeout=5000

优化代码实现:

@Configuration
public class ThreadPoolConfig {
    @Bean("taskExecutor")
    public Executor taskExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        // 核心线程数:CPU核心数 * 2
        executor.setCorePoolSize(Runtime.getRuntime().availableProcessors() * 2);
        // 最大线程数:核心线程数 * 2
        executor.setMaxPoolSize(Runtime.getRuntime().availableProcessors() * 4);
        executor.setQueueCapacity(500);
        executor.setKeepAliveSeconds(60);
        executor.setThreadNamePrefix("task-exec-");
        // 拒绝策略:由调用线程处理
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        executor.initialize();
        return executor;
    }
}

数据库连接池优化

# 优化后的HikariCP配置
spring.datasource.hikari.maximum-pool-size=20  # 根据并发量调整
spring.datasource.hikari.minimum-idle=10
spring.datasource.hikari.idle-timeout=300000
spring.datasource.hikari.max-lifetime=1200000
spring.datasource.hikari.connection-timeout=30000
spring.datasource.hikari.connection-test-query=SELECT 1

动态调整连接池:

@Component
public class DynamicDataSourceConfig {
    @EventListener
    public void handlePoolHealthEvent(PoolHealthEvent event) {
        HikariDataSource dataSource = (HikariDataSource) event.getSource();
        // 根据监控数据动态调整
        if (event.getActiveConnections() > dataSource.getMaximumPoolSize() * 0.8) {
            // 增加连接池大小
            int newSize = dataSource.getMaximumPoolSize() + 5;
            dataSource.setMaximumPoolSize(Math.min(newSize, 50));
        }
    }
}

Redis连接池优化

# 优化后的Redis配置
spring.redis.lettuce.pool.max-active=20
spring.redis.lettuce.pool.max-idle=10
spring.redis.lettuce.pool.min-idle=5
spring.redis.lettuce.pool.max-wait=2000ms
spring.redis.timeout=5000ms

连接池监控实现:

@Component
@Slf4j
public class RedisConnectionMonitor {
    @Autowired
    private LettuceConnectionFactory connectionFactory;
    @Scheduled(fixedDelay = 60000)
    public void monitorConnectionPool() {
        GenericObjectPool<?> pool = (GenericObjectPool<?>) connectionFactory.getPool();
        if (pool != null) {
            log.info("Redis连接池状态 - 活跃: {}, 空闲: {}, 等待: {}, 最大: {}", 
                pool.getNumActive(), 
                pool.getNumIdle(), 
                pool.getNumWaiters(),
                pool.getMaxTotal());
            // 池使用率过高时发送告警
            double usageRate = (double) pool.getNumActive() / pool.getMaxTotal();
            if (usageRate > 0.8) {
                log.warn("Redis连接池使用率超过80%!");
            }
        }
    }
}

缓存配置优化

@Configuration
@EnableCaching
public class CacheConfig extends CachingConfigurerSupport {
    @Bean
    public CacheManager cacheManager(RedisConnectionFactory factory) {
        RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
            .entryTtl(Duration.ofMinutes(30))  // 默认30分钟过期
            .serializeKeysWith(
                RedisSerializationContext.SerializationPair.fromSerializer(
                    new StringRedisSerializer()))
            .serializeValuesWith(
                RedisSerializationContext.SerializationPair.fromSerializer(
                    new GenericJackson2JsonRedisSerializer()));
        // 针对不同缓存设置不同过期时间
        Map<String, RedisCacheConfiguration> configMap = new HashMap<>();
        configMap.put("product", config.entryTtl(Duration.ofMinutes(10)));  // 商品缓存10分钟
        configMap.put("category", config.entryTtl(Duration.ofHours(1)));    // 分类缓存1小时
        configMap.put("user", config.entryTtl(Duration.ofMinutes(5)));      // 用户缓存5分钟
        return RedisCacheManager.builder(factory)
            .cacheDefaults(config)
            .withInitialCacheConfigurations(configMap)
            .build();
    }
}

连接池监控告警

@Component
@Slf4j
public class ConnectionPoolMonitor {
    private final Map<String, ConnectionPoolMetrics> poolMetrics = new ConcurrentHashMap<>();
    @EventListener
    public void handleMetricsEvent(MetricsEvent event) {
        if (event instanceof ConnectionPoolMetrics) {
            ConnectionPoolMetrics metrics = (ConnectionPoolMetrics) event;
            poolMetrics.put(metrics.getPoolName(), metrics);
            // 检查是否需要告警
            if (metrics.getActiveConnections() > metrics.getMaxPoolSize() * 0.8) {
                sendAlert(metrics);
            }
        }
    }
    @Scheduled(fixedRate = 30000)
    public void reportMetrics() {
        poolMetrics.forEach((name, metrics) -> {
            log.info("连接池 [{}] - 活跃: {}/{}, 等待: {}", 
                name,
                metrics.getActiveConnections(),
                metrics.getMaxPoolSize(),
                metrics.getPendingConnections());
        });
    }
}

JVM参数优化

# JVM启动参数优化
JAVA_OPTS="
  -Xms2g -Xmx2g                    # 堆内存初始和最大
  -Xmn1g                           # 新生代大小
  -XX:MetaspaceSize=256m           # 元空间
  -XX:MaxMetaspaceSize=256m
  -XX:+UseG1GC                     # 使用G1垃圾回收器
  -XX:MaxGCPauseMillis=200         # 最大GC暂停时间
  -XX:ParallelGCThreads=4          # 并行GC线程数
  -XX:ConcGCThreads=2              # 并发GC线程数
  -XX:+PrintGCDetails              # 打印GC详情
  -XX:+PrintGCDateStamps           # 打印GC时间戳
  -Xloggc:/logs/gc.log            # GC日志文件
  -Djava.security.egd=file:/dev/./urandom  # 加快随机数生成
"

性能对比

指标 优化前 优化后 提升
TPS 500 1200 140%
平均响应时间 500ms 120ms 76%
连接池使用率 95% 60% 36%
系统资源消耗 CPU 80% CPU 50% 37%

监控配置

# application.yml - 监控配置
management:
  endpoints:
    web:
      exposure:
        include: health,metrics,prometheus
  metrics:
    tags:
      application: shop-service
    export:
      prometheus:
        enabled: true
    distribution:
      percentiles-histogram:
        http.server.requests: true
        db: true
  1. 线程池设置:根据CPU核心数和业务类型调整
  2. 连接池监控:实时监控连接使用率,动态调整
  3. 缓存策略:不同业务设置不同过期时间
  4. 资源隔离:核心业务和非核心业务使用独立连接池
  5. 降级策略:高负载时启用降级,保证核心业务可用

这个案例展示了如何通过细致配置来优化系统资源,提升系统性能和稳定性,实际应用时需要根据具体业务场景和监控数据进行调整。

抱歉,评论功能暂时关闭!