springboot结合Redis的Lettuce响应池连接错误:io.lettuce.core.RedisCommandTimeoutException:Commandtimedout
原创1.最大可能连接/超时设置得太小。
如图所示,检查最大连接数和超时时间并将其打开。
redis:
lettuce:
pool:
MaxTotal: 50 #最大连接数
minIdle: 1
maxWaitMillis: 5000
maxIdle: 5
testOnBorrow: true
testOnReturn: true
testWhileIdle: true
redis-a:
database: 8
hostName: 127.0.0.1
port: 6379
timeout: 5000 #超时时间
redis-b:
database: 8
hostName: 172.16.35.60
port: 31105
password: tenxcloud
timeout: 5000 #超时时间
2.链接池中的链接断开
这个问题有两个原因:
1、Lettuce 自适应拓扑刷新(Adaptive updates)具有定时拓扑刷新(Periodic updates) 默认情况下处于禁用状态。
2,使用的项目k8s做docker集装箱化部署,k8s如果设置空闲连接超时,则会断开连接,因此当从连接池中获取断开连接时,将报告错误。
解决方案是一致的:
方案1:每个环节的自动验证(pro-test易于使用)
说明:lettuce提供了一种检查连接的方法,lettuce提供验证连接的方法。 只是它在默认情况下没有打开。
如果您打开它,您将在每次获得连接时进行检查,并打开获取连接的检查。
@Component
@Slf4j
public class LettuceConnectionValidConfig implements InitializingBean {
@Autowired
private RedisConnectionFactory redisConnectionFactory;
@Override
public void afterPropertiesSet() throws Exception {
if(redisConnectionFactory instanceof LettuceConnectionFactory){
LettuceConnectionFactory c=(LettuceConnectionFactory)redisConnectionFactory;
c.setValidateConnection(true);
}
}
}
方案2:定时任务
描述:每2第二次检查异常lettuce连接是否正常,解决长期闲置lettuce连接已关闭netty无法及时监控的问题。
@Component
@Slf4j
public class LettuceConnectionValidTask {
@Autowired
private RedisConnectionFactory redisConnectionFactory;
@Scheduled(cron="0/2 * * * * ?")
public void task() {
if(redisConnectionFactory instanceof LettuceConnectionFactory){
LettuceConnectionFactory c=(LettuceConnectionFactory)redisConnectionFactory;
c.validateConnection();
}
}
}
方案三:springboot2.3在上述版本中,可以添加配置分辨率。
# 解决redis 240第二个超时问题
lettuce:
cluster:
refresh:
adaptive: true
period: 20
方案4:排除lettuce,采用jedis。
org.springframework.boot
spring-boot-starter-data-redis
io.lettuce
lettuce-core
redis.clients
jedis
请注意,配置文件放置。lettuce.pool换成jedis.pool。
场景5:重写连接工厂实例(强烈建议)。
描述:重写连接工厂实例并进行更改。LettuceClientConfiguration 打开拓扑更新。
@Configuration
public class RedisConfig {
@Autowired
private RedisProperties redisProperties;
//这是一个固定模板。
//我定义了一个RedisTemplate
@Bean
@SuppressWarnings("all")
public RedisTemplate<String, Object> redisTemplate(@Qualifier("lettuceConnectionFactoryUvPv") RedisConnectionFactory factory) {
RedisTemplate<String, Object> template = new RedisTemplate<>();
template.setConnectionFactory(factory);
//Json串行化配置
Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<Object>(Object.class);
ObjectMapper om = new ObjectMapper();
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
om.activateDefaultTyping(om.getPolymorphicTypeValidator());
om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
//解决序列化问题
om.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
jackson2JsonRedisSerializer.setObjectMapper(om);
//String的序列化
StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
//key采用String如何序列化
template.setKeySerializer(stringRedisSerializer);
//hash的key也采用String如何序列化
template.setHashKeySerializer(stringRedisSerializer);
//value采用序列化方法。jackson
template.setValueSerializer(jackson2JsonRedisSerializer);
//hash的value采用序列化方法。jackson
template.setHashValueSerializer(jackson2JsonRedisSerializer);
template.afterPropertiesSet();
return template;
}
/**
* 为RedisTemplate配置Redis连接工厂实施
* LettuceConnectionFactory实现了RedisConnectionFactory接口
* UVPV用Redis
*
* @return 返回LettuceConnectionFactory
*/
@Bean(destroyMethod = "destroy")
//重要的是要在构建中注意这一点。LettuceConnectionFactory 如果不使用内置destroyMethod,可能导致Redis连接早于其他Bean被销毁
public LettuceConnectionFactory lettuceConnectionFactoryUvPv() throws Exception {
List<String> clusterNodes = redisProperties.getCluster().getNodes();
Set<RedisNode> nodes = new HashSet<>();
clusterNodes.forEach(address -> nodes.add(new RedisNode(address.split(":")[0].trim(), Integer.parseInt(address.split(":")[1]))));
RedisClusterConfiguration clusterConfiguration = new RedisClusterConfiguration();
clusterConfiguration.setClusterNodes(nodes);
clusterConfiguration.setPassword(RedisPassword.of(redisProperties.getPassword()));
clusterConfiguration.setMaxRedirects(redisProperties.getCluster().getMaxRedirects());
RedisStandaloneConfiguration redisStandaloneConfiguration=new RedisStandaloneConfiguration();
redisStandaloneConfiguration.setHostName(redisProperties.getHost());
redisStandaloneConfiguration.setPassword(redisProperties.getPassword());
redisStandaloneConfiguration.setDatabase(redisProperties.getDatabase());
redisStandaloneConfiguration.setPort(redisProperties.getPort());
GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig();
poolConfig.setMaxIdle(redisProperties.getLettuce().getPool().getMaxIdle());
poolConfig.setMinIdle(redisProperties.getLettuce().getPool().getMinIdle());
poolConfig.setMaxTotal(redisProperties.getLettuce().getPool().getMaxActive());
return new LettuceConnectionFactory(redisStandaloneConfiguration, getLettuceClientConfiguration(poolConfig));
}
/**
* 配置LettuceClientConfiguration 包括线程池配置和安全项配置
*
* @param genericObjectPoolConfig common-pool2线程池
* @return lettuceClientConfiguration
*/
private LettuceClientConfiguration getLettuceClientConfiguration(GenericObjectPoolConfig genericObjectPoolConfig) {
/*
ClusterTopologyRefreshOptions该配置用于打开自适应刷新和定时刷新。如果自适应刷新未打开,Redis群集更改将导致连接异常!
*/
ClusterTopologyRefreshOptions topologyRefreshOptions = ClusterTopologyRefreshOptions.builder()
//启用自适应刷新
//.enableAdaptiveRefreshTrigger(ClusterTopologyRefreshOptions.RefreshTrigger.MOVED_REDIRECT, ClusterTopologyRefreshOptions.RefreshTrigger.PERSISTENT_RECONNECTS)
//打开所有自适应刷新,MOVED,ASK,PERSISTENT都会触发
.enableAllAdaptiveRefreshTriggers()
// 自适应刷新超时(默认30秒)
.adaptiveRefreshTriggersTimeout(Duration.ofSeconds(25)) //关闭和打开后的默认时间为30秒
// 打开循环刷新
.enablePeriodicRefresh(Duration.ofSeconds(20)) // 关闭和打开后的默认时间为60秒 ClusterTopologyRefreshOptions.DEFAULT_REFRESH_PERIOD 60 .enablePeriodicRefresh(Duration.ofSeconds(2)) = .enablePeriodicRefresh().refreshPeriod(Duration.ofSeconds(2))
.build();
return LettucePoolingClientConfiguration.builder()
.poolConfig(genericObjectPoolConfig)
.clientOptions(ClusterClientOptions.builder().topologyRefreshOptions(topologyRefreshOptions).build())
//将appID进线连接,方便Redis在监视中查看
//.clientName(appName + "_lettuce")
.build();
}
}
重写连接工厂实例(强烈建议)。
版权声明
所有资源都来源于爬虫采集,如有侵权请联系我们,我们将立即删除
itfan123




