本文共 4259 字,大约阅读时间需要 14 分钟。
记一次线上环境 redis偶尔连接超时报错 解决
贴出本地控制台日志
说实话,很痛苦,跟进很久了,一直认为的jvm程序所使用的配置的连接池框架问题
因为程序为 springboot 2 spring 5 ;那么默认连接池为 lettuce
起初认为是原有的jedis 转换到 lettuce存在的各种bug问题,可能没配置好;
网上也寻找了相关的文章,发现大多数人的解决方案,就是在springboot的自动注入的配置文件中,配置不对,说spring.redis.timeout配置为0,导致不允许超时,那么就会抛出该异常;
所以只需要将其改为合理的范围即可,比如10s,那么本人也试过了,发现不顶用。
此处贴出配置文件(注:rediss不是写错,是故意不使用自动配置注入的):
然后就是连接池的问题了,本人尝试使用自定义注入连接池使用,不使用自动注入(此处怀疑是自动注入问题)结果也发现不行,
那么再怀疑是配置项不对,例如连接池的最小空闲链接、最大空闲链接数不合理,那么我本地在尝试调整的时候,本地模拟运行一段时间,发现还是会时不时抛出超时问题;
此处贴出本人的自定义注入配置文件(一个lettuce连接工厂)
/** * @description: LettuceConfiguration * @author: Wang Ji * @create: 2021/01/22 21:24 */@Slf4j@Configuration@AutoConfigureAfter(RedisAutoConfiguration.class)public class LettuceConfig { @Value("${spring.rediss.database}") private int database = 0; @Value("${spring.rediss.host}") private String host; @Value("${spring.rediss.port}") private int port; @Value("${spring.rediss.password}") private String password = null; @Value("${spring.rediss.timeout}") private int timeout = 5000; @Value("${spring.rediss.lettuce.pool.max-idle}") private int maxIdle = 8; @Value("${spring.rediss.lettuce.pool.min-idle}") private int minIdle = 0; @Value("${spring.rediss.lettuce.pool.max-active}") private int maxActive = 8; @Value("${spring.rediss.lettuce.pool.max-wait}") private long maxWait; /** * lettuce 连接工厂 * * @param genericObjectPoolConfig * @return */ @Bean("redisConnectionFactory") public RedisConnectionFactory redisConnectionFactory(@Qualifier("genericObjectPoolConfig") GenericObjectPoolConfig genericObjectPoolConfig) { // 单机版配置 RedisStandaloneConfiguration redisStandaloneConfiguration = new RedisStandaloneConfiguration(); redisStandaloneConfiguration.setDatabase(database); redisStandaloneConfiguration.setHostName(host); redisStandaloneConfiguration.setPort(port); redisStandaloneConfiguration.setPassword(RedisPassword.of(password)); // 集群版配置// RedisClusterConfiguration redisClusterConfiguration = new RedisClusterConfiguration();// String[] serverArray = clusterNodes.split(",");// Setnodes = new HashSet ();// for (String ipPort : serverArray) {// String[] ipAndPort = ipPort.split(":");// nodes.add(new RedisNode(ipAndPort[0].trim(), Integer.valueOf(ipAndPort[1])));// }// redisClusterConfiguration.setPassword(RedisPassword.of(password));// redisClusterConfiguration.setClusterNodes(nodes);// redisClusterConfiguration.setMaxRedirects(maxRedirects); LettuceClientConfiguration clientConfig = LettucePoolingClientConfiguration.builder() .commandTimeout(Duration.ofMillis(timeout)) .poolConfig(genericObjectPoolConfig) .build(); RedisConnectionFactory redisConnectionFactory = new LettuceConnectionFactory(redisStandaloneConfiguration, clientConfig); if (ConnectionUtils.isLettuce(redisConnectionFactory)) { log.warn("// RedisConnectionFactory is Lettuce"); } else if (ConnectionUtils.isJedis(redisConnectionFactory)) { log.warn("// RedisConnectionFactory is Jedis"); } return redisConnectionFactory; } /** * GenericObjectPoolConfig 连接池配置 * * @return */ @Bean("genericObjectPoolConfig") public GenericObjectPoolConfig genericObjectPoolConfig() { GenericObjectPoolConfig genericObjectPoolConfig = new GenericObjectPoolConfig<>(); genericObjectPoolConfig.setMaxIdle(maxIdle); genericObjectPoolConfig.setMinIdle(minIdle); genericObjectPoolConfig.setMaxTotal(maxActive); genericObjectPoolConfig.setMaxWaitMillis(maxWait); return genericObjectPoolConfig; }}
然后在一篇文章中也看到,可能存在一个这样的问题,redis在长时间空闲状态,会自动重启?
本人没验证过,猜测可能是某种垃圾回收策略,内存碎片化整理。有兴趣的同学可以去研究一下。
那么本人再次怀疑,可能就是redis本身的config配置不对,因为笔者对于redis的自己的服务器上的部署都是全部自定义过的,也就是说,很多配置,都对其进行了适合自己项目的配置,比如回收策略,数据库数量,最大连接数量,等等等,那么按常理来说,redis的本身服务上也会有一个超时配置。
一找,果不其然有个超时配置;
但是这个配置是:客户端闲置N秒后关闭连接(0禁用)
按道理来说,0应该是禁用了主动关闭连接的配置
这里,我将尝试改为300s 后 超时
那么并且修改配置文件中的 多少秒检测一次空闲状态
修改这样,然后我后面再尝试运行一段时间,看看结果怎样
注意,此调试方案建议不要直接用于生产环境
因为每个公司服务的策略都不一样,毕竟脱离业务的架构方案都是耍流氓,建议可以以拓展知识面的方式阅读本文章。
转载地址:https://changemax.blog.csdn.net/article/details/113039842 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!