现象
- 之前写了一篇文章:Spring redis使用报错Read timed out排查解决,解决超时问题
- 后面发现解决的不彻底,仍有报错
- 详细查看了下源码,发现不同版本里,参数名不一样,之前的参数设置,并没有在新版本里生效
报错一
- 核心报错提示是这一句:
JedisConnectionException: java.net.SocketTimeoutException: Read timed out
- 使用jedis连接时,连接超时
SocketTimeout
,即与Redis服务器的连接超时
2023-03-29 10:54:38.186 ERROR 9136 --- [ntainer#7-0-C-1] c.n.r.service.IntersectionQueryService : Exception in getIntersectionById() with cause = 'redis.clients.jedis.exceptions.JedisConnectionException: java.net.SocketTimeoutException: Read timed out' and exception = 'java.net.SocketTimeoutException: Read timed out; nested exception is redis.clients.jedis.exceptions.JedisConnectionException: java.net.SocketTimeoutException: Read timed out'
org.springframework.data.redis.RedisConnectionFailureException: java.net.SocketTimeoutException: Read timed out; nested exception is redis.clients.jedis.exceptions.JedisConnectionException: java.net.SocketTimeoutException: Read timed out
at org.springframework.data.redis.connection.jedis.JedisExceptionConverter.convert(JedisExceptionConverter.java:65)
at org.springframework.data.redis.connection.jedis.JedisExceptionConverter.convert(JedisExceptionConverter.java:42)
at org.springframework.data.redis.PassThroughExceptionTranslationStrategy.translate(PassThroughExceptionTranslationStrategy.java:44)
at org.springframework.data.redis.FallbackExceptionTranslationStrategy.translate(FallbackExceptionTranslationStrategy.java:42)
at org.springframework.data.redis.connection.jedis.JedisConnection.convertJedisAccessException(JedisConnection.java:187)
at org.springframework.data.redis.connection.jedis.JedisConnection.doWithJedis(JedisConnection.java:802)
at org.springframework.data.redis.connection.jedis.JedisConnection.doInvoke(JedisConnection.java:160)
at org.springframework.data.redis.connection.jedis.JedisConnection.lambda$new$0(JedisConnection.java:69)
at org.springframework.data.redis.connection.jedis.JedisInvoker$Synchronizer.invoke(JedisInvoker.java:1027)
at org.springframework.data.redis.connection.jedis.JedisInvoker$DefaultSingleInvocationSpec.getOrElse(JedisInvoker.java:946)
at org.springframework.data.redis.connection.jedis.JedisStringCommands.setEx(JedisStringCommands.java:176)
at org.springframework.data.redis.connection.DefaultedRedisConnection.setEx(DefaultedRedisConnection.java:334)
at org.springframework.data.redis.connection.DefaultStringRedisConnection.setEx(DefaultStringRedisConnection.java:1138)
at org.springframework.data.redis.core.DefaultValueOperations$8.potentiallyUsePsetEx(DefaultValueOperations.java:337)
at org.springframework.data.redis.core.DefaultValueOperations$8.doInRedis(DefaultValueOperations.java:330)
at org.springframework.data.redis.core.RedisTemplate.execute(RedisTemplate.java:223)
at org.springframework.data.redis.core.RedisTemplate.execute(RedisTemplate.java:190)
at org.springframework.data.redis.core.AbstractOperations.execute(AbstractOperations.java:97)
at org.springframework.data.redis.core.DefaultValueOperations.set(DefaultValueOperations.java:325)
at com.newatc.radar.service.IntersectionQueryService.getAllIntersections(IntersectionQueryService.java:70)
报错二
- 核心报错提示是这一句:
Error while validating pooled Jedis object
- 连接池内的Jedis对象已经失效或已经关闭,没有可用的jedis客户端
2023-08-24 09:44:23.721 ERROR 92250 --- [ns-pool-evictor] redis.clients.jedis.JedisFactory : Error while validating pooled Jedis object.
redis.clients.jedis.exceptions.JedisConnectionException: java.net.SocketTimeoutException: Read timed out
at redis.clients.jedis.util.RedisInputStream.ensureFill(RedisInputStream.java:205)
at redis.clients.jedis.util.RedisInputStream.readByte(RedisInputStream.java:43)
at redis.clients.jedis.Protocol.process(Protocol.java:162)
at redis.clients.jedis.Protocol.read(Protocol.java:227)
at redis.clients.jedis.Connection.readProtocolWithCheckingBroken(Connection.java:352)
at redis.clients.jedis.Connection.getStatusCodeReply(Connection.java:270)
at redis.clients.jedis.BinaryJedis.ping(BinaryJedis.java:380)
at redis.clients.jedis.JedisFactory.validateObject(JedisFactory.java:214)
at org.apache.commons.pool2.impl.GenericObjectPool.evict(GenericObjectPool.java:745)
at org.apache.commons.pool2.impl.BaseGenericObjectPool$Evictor.run(BaseGenericObjectPool.java:160)
at org.apache.commons.pool2.impl.EvictionTimer$WeakRunner.run(EvictionTimer.java:113)
at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515)
at java.base/java.util.concurrent.FutureTask.runAndReset(FutureTask.java:305)
at java.base/java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:305)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
at java.base/java.lang.Thread.run(Thread.java:829)
Caused by: java.net.SocketTimeoutException: Read timed out
at java.base/java.net.SocketInputStream.socketRead0(Native Method)
at java.base/java.net.SocketInputStream.socketRead(SocketInputStream.java:115)
at java.base/java.net.SocketInputStream.read(SocketInputStream.java:168)
at java.base/java.net.SocketInputStream.read(SocketInputStream.java:140)
at java.base/java.net.SocketInputStream.read(SocketInputStream.java:126)
at redis.clients.jedis.util.RedisInputStream.ensureFill(RedisInputStream.java:199)
... 16 common frames omitted
2023-08-24 09:44:25.724 ERROR 92250 --- [ns-pool-evictor] redis.clients.jedis.JedisFactory : Error while validating pooled Jedis object.
redis.clients.jedis.exceptions.JedisConnectionException: java.net.SocketTimeoutException: Read timed out
at redis.clients.jedis.util.RedisInputStream.ensureFill(RedisInputStream.java:205)
at redis.clients.jedis.util.RedisInputStream.readByte(RedisInputStream.java:43)
at redis.clients.jedis.Protocol.process(Protocol.java:162)
at redis.clients.jedis.Protocol.read(Protocol.java:227)
at redis.clients.jedis.Connection.readProtocolWithCheckingBroken(Connection.java:352)
at redis.clients.jedis.Connection.getStatusCodeReply(Connection.java:270)
at redis.clients.jedis.BinaryJedis.ping(BinaryJedis.java:380)
at redis.clients.jedis.JedisFactory.validateObject(JedisFactory.java:214)
at org.apache.commons.pool2.impl.GenericObjectPool.evict(GenericObjectPool.java:745)
at org.apache.commons.pool2.impl.BaseGenericObjectPool$Evictor.run(BaseGenericObjectPool.java:160)
at org.apache.commons.pool2.impl.EvictionTimer$WeakRunner.run(EvictionTimer.java:113)
at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515)
at java.base/java.util.concurrent.FutureTask.runAndReset(FutureTask.java:305)
at java.base/java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:305)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
at java.base/java.lang.Thread.run(Thread.java:829)
Caused by: java.net.SocketTimeoutException: Read timed out
at java.base/java.net.SocketInputStream.socketRead0(Native Method)
at java.base/java.net.SocketInputStream.socketRead(SocketInputStream.java:115)
at java.base/java.net.SocketInputStream.read(SocketInputStream.java:168)
at java.base/java.net.SocketInputStream.read(SocketInputStream.java:140)
at java.base/java.net.SocketInputStream.read(SocketInputStream.java:126)
at redis.clients.jedis.util.RedisInputStream.ensureFill(RedisInputStream.java:199)
... 16 common frames omitted
解决
- 报错是发生在我们的环境,事实上,我们的平台并没有那么高的并发量,只有一些造数据脚本在跑和调用redis
- 而且所有应用服务和redis服务,都在一个内网环境里,不应该有网络波动的问题,但发生这个报错时,使用可视化工具连接redis,可以发现,Redis服务是正常的
- 最终发现,是我们没有针对新版本,配置好超时参数
- 原有配置
spring:
redis:
host: 192.168.1.50
port: 6379
password:
database: 0
jedis:
pool:
min-idle: 10
max-idle: 400
max-wait: 30000
max-active: 200
- 查看了源码后发现,少了对于redis客户端连接维护的超时时间设置,这个超时时间默认是2s,有时候是不够用的
- 当大并发量来临,或者大量对象存储更新时,阻塞可能会超过2s时,就会报错
SocketTimeoutException
- 新的配置(时间可以写毫秒,也可以带单位)
-
spring.redis.timeout
:是指与redis服务器的读写超时时间,读写操作时会判断这个 -
spring.redis.connect-timeout
:是指与redis服务器的连接超时时间,默认2s,这个可以设置大一点,例如30s,保证短时的网络波动不影响连接 -
spring.redis.jedis.pool.min-idle
:最小空闲连接,可以根据需要写,我这里设置为8 -
spring.redis.jedis.pool.max-idle
:最大空闲连接,可以根据需要写,我这里设置为200,够用了 -
spring.redis.jedis.pool.max-wait
:连接池最大阻塞等待时间(使用负值表示没有限制),这个是指服务从连接池获取连接的等待时间,我这里设置为30s,够用了 -
spring.redis.jedis.pool.max-active
:连接池最大连接数(使用负值表示没有限制),根据我们的应用数量设置,我这里设置256,足够用了
spring:
redis:
host: 192.168.1.50
port: 6379
password:
database: 0
timeout: 30s # 读写超时
connect-timeout: 60s #连接超时
jedis:
pool:
min-idle: 8 # 最小空闲连接
max-idle: 200 # 最大空闲连接
max-wait: 30s # 连接池最大阻塞等待时间(使用负值表示没有限制)
max-active: 256 # 连接池最大连接数(使用负值表示没有限制)
- 总结一下,一开始只配置了参数
spring.redis.jedis.pool.max-wait
连接池最大阻塞等待时间,而没有配置spring.redis.timeout
和spring.redis.connect-timeout
,导致偶发的超时 - 配置上这两个参数后,就没有遇到超时报错了
- 最后再介绍下Jedis连接池吧
Jedis连接池
Jedis连接池是用于管理Jedis客户端连接的一种机制。Jedis是一个非常流行的Java Redis客户端,它允许Java开发人员与Redis服务器进行交互。
Jedis连接池的目的是为了提高应用程序与Redis服务器之间的性能和可扩展性。通过连接池,应用程序可以重复利用现有的连接而不是创建新的连接,从而减少连接的创建和销毁的开销。
Jedis连接池的实现中有几个主要的组件:
-
连接池配置(Config):用于设置连接池的参数,如最大连接数、最大空闲连接数、连接超时时间等。
-
连接池对象(JedisPool):用于创建和管理Jedis连接。
-
Jedis连接(Jedis):用于与Redis服务器进行交互的对象。
连接池的工作原理如下:文章来源:https://www.toymoban.com/news/detail-804561.html
- 初始化:当连接池被创建时,它会根据配置参数建立一定数量的连接,并放入连接池中。
- 借用连接:当应用程序需要与Redis服务器进行交互时,它可以从连接池中获取一个空闲连接。
- 使用连接:应用程序使用连接进行操作,如执行命令、读写数据等操作。
- 归还连接:应用程序完成操作后,将连接归还给连接池,以便其他线程或请求可以继续使用该连接。
- 连接池管理:连接池会根据预设的策略来管理连接的状态,如连接的获取、释放、逐出等。
使用Jedis连接池可以提高应用程序与Redis服务器之间的性能和资源利用率。通过合理配置连接池的参数,可以控制连接数、连接超时时间、最大空闲连接数等,以适应不同规模的应用程序需求。同时,连接池还可以提供连接的可用性检查、自动重连、连接汇报等功能,提高应用的可靠性和稳定性。文章来源地址https://www.toymoban.com/news/detail-804561.html
到了这里,关于Java连接redis报错timed out问题解决的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!