本文目录导读:

我来提供一个完整的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
问题分析
系统出现以下问题:
- 高并发时响应变慢
- 偶尔出现连接池满异常
- 数据库连接经常超时
优化方案实操
线程池优化
# 优化后的线程池配置 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
- 线程池设置:根据CPU核心数和业务类型调整
- 连接池监控:实时监控连接使用率,动态调整
- 缓存策略:不同业务设置不同过期时间
- 资源隔离:核心业务和非核心业务使用独立连接池
- 降级策略:高负载时启用降级,保证核心业务可用
这个案例展示了如何通过细致配置来优化系统资源,提升系统性能和稳定性,实际应用时需要根据具体业务场景和监控数据进行调整。