当前位置: 首页 > 后端技术 > Java

生产环境Redis连接,长时间无响应被服务器断开问题

时间:2023-04-02 09:58:37 Java

生产环境Redis连接被服务端断开长时间无响应Lettuce客户端,且未指定连接池,当前客户端连接被服务端不知不觉断开连接后产生的errorconnectionresetbypeer,也就是说当前客户端的Redis连接已经被服务器断开了,但是客户端并不知道,当请求进来的时候,Lettuce继续使用当前的Redis连接请求数据时,会提示connectionresetbypeer.一般情况下服务器断开连接时会发送一个FIN包通知客户端,但是当我使用tcpdump监控服务器的tcp传输时,发现Redis服务器的tcp连接已经有一段时间不活跃了,例如,它会在10分钟后收到来自客户端的消息。最后是RST包,但是我的客户端也是用wireshark抓包,并没有把RST包发给服务器,很奇怪。我猜测这可能是服务器对tcp连接的限制,长期不活动导致tcp连接被强行断开。所以线上环境下Redis连接偶尔出现的connectionresetbypeererror是我复现的。既然到这里知道是Redis连接长时间不活动导致的BUG,那么如何解决呢?一开始博主以为重试就可以解决问题,结果发现事情并没有想象的那么简单。上面的代码//查询RedispublicTgetCacheObject(finalStringkey){try{ValueOperationsoperation=redisTemplate.opsForValue();返回操作.get(key);}catch(Exceptione){log.error(e.getMessage(),e);返回retryGetCacheObject(key,3);}}//重试查询RedispublicTretryGetCacheObject(finalStringkey,intretryCount){try{log.info("retryGetCacheObject,key:{},retryCount:{}",key,retryCount);如果(重试次数<=0){返回空值;}Thread.sleep(200L);重试次数--;ValueOperationsoperation=redisTemplate.opsForValue();返回操作.get(key);}catch(Exceptione){log.error(e.getMessage(),e);返回retryGetCacheObject(键,retryCount);}}上面代码表示Redis发送的第一个Query异常发生后,我每200毫秒检查3次。实际运行的时候发现会出现三个connectionresetbypeer的错误,并没有获取到新的Redis连接。我这里解决这个问题的方法其实就是Redis连接出现异常后如何创建一个新的连接来代替它。话不多说直接上代码://Lettuce连接工厂@AutowiredprivateLettuceConnectionFactorylettuceConnectionFactory;/***获取缓存的基本对象。**@paramkey绑定键值*@return绑定键值对应的数据*/publicTgetCacheObject(finalStringkey){try{ValueOperationsoperation=redisTemplate.opsForValue();返回操作.get(key);}catch(Exceptione){log.error(e.getMessage(),e);返回retryGetCacheObject(key,1);}}publicTretryGetCacheObject(finalStringkey,intretryCount){try{log.info("retryGetCacheObject,key:{},retryCount:{}",key,retryCount);如果(重试次数<=0){返回空值;}lettuceConnectionFactory.resetConnection();线程睡眠(200L);重试次数--;ValueOperationsoperation=redisTemplate.opsForValue();返回操作.get(key);}catch(Exceptione){log.error(e.getMessage(),e);返回retryGetCacheObject(键,retryCount);当前Redis连接异常获取数据超过超时时间后,抛出异常,进入retry方法。使用lettuceConnectionFactory.resetConnection()方法重置连接并创建新连接后,继续获取数据,从而正常响应客户端。lettuceConnectionFactory对象是Lettuce的无池连接的工厂实现。它提供`lettuceConnectionFactory.getConnection();生菜连接工厂.initConnection();lettuceConnectionFactory.resetConnection();`等获取和初始化,重置连接的方法配合springboot配置timeout设置获取数据的超时时间为2秒,这样接口请求时间也控制在2秒左右.解决了客户端的无池连接偶尔断开的问题。最后贴出实战项目newbeemall的地址。newbee-mall商城mybatisplus版本实现优惠券领取、支付宝沙盒支付、后台新增搜索、RedisSearch分词检索