spring boot2整合Redis5时报错

症状为:访问某个接口很慢,即时访问成功后报错,再次访问一切正常,但是每隔几分钟访问接口仍然很慢或者报错

2019-08-07 11:34:15.141 ERROR 21076 --- [nio-8080-exec-5] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.data.redis.RedisSystemException: Redis exception; nested exception is io.lettuce.core.RedisException: java.io.IOException: 远程主机强迫关闭了一个现有的连接。] with root cause

具体如下

2019-08-07 11:34:15.141 ERROR 21076 --- [nio-8080-exec-5] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.data.redis.RedisSystemException: Redis exception; nested exception is io.lettuce.core.RedisException: java.io.IOException: 远程主机强迫关闭了一个现有的连接。] with root cause

java.io.IOException: 远程主机强迫关闭了一个现有的连接。
	at sun.nio.ch.SocketDispatcher.read0(Native Method) ~[na:1.8.0_191]
	at sun.nio.ch.SocketDispatcher.read(SocketDispatcher.java:43) ~[na:1.8.0_191]
	at sun.nio.ch.IOUtil.readIntoNativeBuffer(IOUtil.java:223) ~[na:1.8.0_191]
	at sun.nio.ch.IOUtil.read(IOUtil.java:192) ~[na:1.8.0_191]
	at sun.nio.ch.SocketChannelImpl.read(SocketChannelImpl.java:380) ~[na:1.8.0_191]
	at io.netty.buffer.PooledUnsafeDirectByteBuf.setBytes(PooledUnsafeDirectByteBuf.java:288) ~
***省略一些**********************************************************************
	at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30) ~[netty-common-4.1.36.Final.jar:4.1.36.Final]
	at java.lang.Thread.run(Thread.java:748) [na:1.8.0_191]

然后你就百度,上面有说Redis版本问题的,有说时间设置在5秒的,还有什么Redis连接池的客户端.lettuce替换了之前的jedis的,然后你配置如下(网上配置太多,各种版本,我随便列举一个写法)

spring.redis.database=0
### 服务器地址,默认为localhost
spring.redis.host=49.4.4.105
### 链接端口,默认为6379
spring.redis.port=6379
### redis密码默认为空
spring.redis.password=
#处理连接超时等 如 java.io.IOException: 远程主机强迫关闭了一个现有的连接。

#Spring Boot 从 2.0版本开始,将默认的Redis客户端Jedis替换为Lettuce
spring.redis.lettuce.pool.max-active=8
spring.redis.lettuce.pool.max-wait=-1ms
spring.redis.lettuce.pool.max-idle=5
spring.redis.lettuce.pool.min-idle=0
spring.redis.timeout=50000ms

 然后还是报错,大概是这样子的

io.lettuce.core.RedisCommandTimeoutException: Command timed out after 5 second(s)
	at io.lettuce.core.ExceptionFactory.createTimeoutException(ExceptionFactory.java:51) ~[lettuce-core-5.1.6.RELEASE.jar:na]
	at io.lettuce.core.LettuceFutures.awaitOrCancel(LettuceFutures.java:114) ~[lettuce-core-5.1.6.RELEASE.jar:na]
***省略一些*******************************************************************	
[na:1.8.0_191]
	at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-embed-core-9.0.19.jar:9.0.19]
	at java.lang.Thread.run(Thread.java:748) [na:1.8.0_191]

到这里还是没有解决,依赖啊什么的都是正确的,感觉没有什么问题,网上有的修改了当时可以了,喜出望外的给博主感谢并在评论区证实修改redis超时时间有效(当然有的确实生效了,只是他们没有多次测试而已)

归根结底,是Redis配置conf文件(在Linux服务器(如果Windows跑的redis就在Windows找)安装redis的路径去找)没有配置正确,在130行左右(可以使用ctr+F搜索 tcp-keepalive),将它改成1-50左右的数字,比如改成tcp-keepalive,之前是0或者300貌似,改成小一点的数字就行了,原理百度或者根据配置文件的注释英文翻译一下,记得改完重启Redis.

忒别注意:springboot配置redis超时配置时间  spring.redis.lettuce.shutdown-timeout=100

大于Redis服务器配置的 tcp-keepalive 存活时间(比如60)就行,你想吧,超时100>60符合正常逻辑,如果超时关闭时长<存活时长(tcp-keepalive),就相当于你追女生,追到要答应了,在答应前你放弃了,那么竹篮打水一场空,给你一个 远程主机强迫关闭了一个现有的连接  的宿命哈哈哈

我的springboot版本是2.1,Redis是5,貌似Redis3.2.1开始默认60,所以建议改成1-20之间就不那么卡或者报错.

 

貌似有人还是不行,看一下是否使用了redisson,用了的话尝试升级一下这个版本,比如升级到3.16.1,试一试呢

<dependency>
    <groupId>org.redisson</groupId>
    <artifactId>redisson</artifactId>
    <version>3.16.1</version>
</dependency>