生产环境 Redis 连接,长时间无响应被服务器断开问题
上个月线上生产环境有几个接口出现异常响应,查看生产日志后发现,如下错误
线上 Redis 客户端使用的是SpringBoot
默认的Lettuce
客户端,并且没有指定连接池,connection reset by peer
这个错误是当前客户端连接在不知情的情况下被服务端断开后产生,也就是说当前客户端 Redis 连接已经在服务端断开了,但是客户端并不知道,当请求进来时,Lettuce
继续使用当前 Redis 连接请求数据时,就会提示connection reset by peer
。
一般情况下服务端断开连接都会发送FIN
包通知客户端,但是当我在用tcpdump
监控服务端 tcp 传输后,发现 Redis 服务端 tcp 连接在无活动一段时间,比如 10 分钟后会收到来自客户端的RST
包,然而我的客户端也在使用 wireshark 抓包中,并没有发送给服务端RST
包,这就很奇怪了,猜测这里是可能是服务器对 tcp 连接的限制导致,对长时间无活动的 tcp 连接强制断开处理。所以这里线上环境 Redis 连接偶尔产生connection reset by peer
错误是被我复现出来了。
既然这里知道是 Redis 连接长时间无活动后被断开导致的 bug,那怎么解决?
博主一开始以为重试可以解决,但是发现事情没有想象的简单。上代码
上面代码的意思是第一次查询 Redis 发生异常后,每隔 200 毫秒在查 3 次。当实际运行时,发现这里会提示三次connection reset by peer
错误,一直没有取到新的 Redis 连接。
到这里这个问题的我的解决思路其实就是怎么在 Redis 连接发生异常后,怎么创建一条新的连接进行代替。
不多说直接上代码:
在用当前 Redis 连接获取数据发生异常超过timeout
间隔后,抛出异常,进入重试方法,使用 lettuceConnectionFactory.resetConnection()
方法进行连接重置,创建一条新的连接后,继续获取数据,从而正常响应客户端。lettuceConnectionFactory
对象是对Lettuce
无池化连接的工厂实现,提供了 lettuceConnectionFactory.getConnection(); lettuceConnectionFactory.initConnection(); lettuceConnectionFactory.resetConnection();
等获取、初始化、重置连接的方法
配合springboot
配置timeout
将获取数据的超时时间设置为 2 秒,从而将接口请求耗时也控制在 2 秒左右
到此生产环境这里SpringBoot
项目下Lettuce
客户端无池化连接偶尔断开的 bug 算是解决了
最后贴一下实战项目地址newbeemall,newbee-mall 商城的 mybatis plus 版本 实现了优惠卷领取, 支付宝沙箱支付,后台添加搜索,RedisSearch 分词检索
版权声明: 本文为 InfoQ 作者【越长大越悲伤】的原创文章。
原文链接:【http://xie.infoq.cn/article/c3c05e6f7a51d530ac60441d1】。文章转载请联系作者。
评论