springboot2.x集成lettuce连接redis集群报超时异常怎么解决-亚博电竞手机版

springboot2.x集成lettuce连接redis集群报超时异常怎么解决

本篇内容主要讲解“springboot2.x集成lettuce连接redis集群报超时异常怎么解决”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“springboot2.x集成lettuce连接redis集群报超时异常怎么解决”吧!

背景:最近在对一新开发springboot系统做压测,发现刚开始压测时,可以正常对redis集群进行数据存取,但是暂停几分钟后,接着继续用jmeter进行压测时,发现redis就开始突然疯狂爆出异常提示:command timed out after 6 second(s)……

1causedby:io.lettuce.core.rediscommandtimeoutexception:commandtimedoutafter6second(s)2atio.lettuce.core.exceptionfactory.createtimeoutexception(exceptionfactory.java:51)3atio.lettuce.core.lettucefutures.awaitorcancel(lettucefutures.java:114)4atio.lettuce.core.cluster.clusterfuturesyncinvocationhandler.handleinvocation(clusterfuturesyncinvocationhandler.java:123)5atio.lettuce.core.internal.abstractinvocationhandler.invoke(abstractinvocationhandler.java:80)6atcom.sun.proxy.$proxy134.mget(unknownsource)7atorg.springframework.data.redis.connection.lettuce.lettucestringcommands.mget(lettucestringcommands.java:119)8...15commonframesomitted

我急忙检查redis集群,发现集群里的各节点都一切正常,且cpu和内存使用率还不到百分之二十,看着这一切,我突然陷入漫长的沉思,到底是哪里出现问题……百度一番,发现不少人都出现过类似情况的,有人说把超时timeout设置更大一些就可以解决了。我按照这样的解决方法,把超时timeout的值设置到更大后,依然没有解决该超时问题。

其中,springboot操作redis的依赖包是——

12org.springframework.boot3spring-boot-starter-data-redis4

集群配置——

1redis:2timeout:6000ms3cluster:4nodes:5-xxx.xxx.x.xxx:63796-xxx.xxx.x.xxx:63797-xxx.xxx.x.xxx:63798jedis:9pool:10max-active:100011max-idle:1012min-idle:513max-wait:-1

点进spring-boot-starter-data-redis进去,发现里面包含了lettuce的依赖:

springboot1.x默认使用的是jedis,到了springboot2.x就默认使用了lettuce。我们可以简单验证一下,在redis驱动加载配置类里,输出一下redisconnectionfactory信息:

1@configuration2@autoconfigureafter(redisautoconfiguration.class)3publicclassconfiguration{4@bean5publicstringredistemplateredistemplate(redisconnectionfactoryfactory){6log.info("测试打印驱动类型:" factory);7}

打印输出——

测试打印驱动类型:org.springframework.data.redis.connection.lettuce.lettuceconnectionfactory@74ee761e

可见,这里使用正是是lettuce驱动连接,因此,当把它换成以前用的比较多的jedis驱动连接时,就没有再出现这个command timed out after 6 second(s)问题了。

12org.springframework.boot3spring-boot-starter-data-redis456io.lettuce7lettuce-core89101112redis.clients13jedis14

那么问题来了,springboot2.x是如何默认使用了lettuce,这得去研究下里面的部分代码。我们可以可进入到springboot2.x自动装配模块的redis部分,其中有一个redisautoconfiguration类,其主要作用是对springboot自动配置连接redis类:

1@configuration(2proxybeanmethods=false3)4@conditionalonclass({redisoperations.class})5@enableconfigurationproperties({redisproperties.class})6@import({lettuceconnectionconfiguration.class,jedisconnectionconfiguration.class})7publicclassredisautoconfiguration{8publicredisautoconfiguration(){9}10......省略11}

这里只需要关注里面的一行注解:

12@import({lettuceconnectionconfiguration.class,jedisconnectionconfiguration.class})3

这就意味着使用spring-boot-starter-data-redis依赖时,可自动导入lettuce和jedis两种驱动,按理来说,不会同时存在两种驱动,这样没有太大意义,因此,这里的先后顺序就很重要了,为什么这么说呢?

分别进入到lettuceconnectionconfiguration.class与jedisconnectionconfiguration.class当中,各自展示本文需要涉及到的核心代码:

1//lettuceconnectionconfiguration2@conditionalonclass({redisclient.class})3classlettuceconnectionconfigurationextendsredisconnectionconfiguration{4......省略5@bean6@conditionalonmissingbean({redisconnectionfactory.class})7lettuceconnectionfactoryredisconnectionfactory(objectproviderbuildercustomizers,clientresourcesclientresources)throwsunknownhostexception{8lettuceclientconfigurationclientconfig=this.getlettuceclientconfiguration(buildercustomizers,clientresources,this.getproperties().getlettuce().getpool());9returnthis.createlettuceconnectionfactory(clientconfig);10}11}12//jedisconnectionconfiguration13@conditionalonclass({genericobjectpool.class,jedisconnection.class,jedis.class})14classjedisconnectionconfigurationextendsredisconnectionconfiguration{15......省略16@bean17@conditionalonmissingbean({redisconnectionfactory.class})18jedisconnectionfactoryredisconnectionfactory(objectproviderbuildercustomizers)throwsunknownhostexception{19returnthis.createjedisconnectionfactory(buildercustomizers);20}21}22

可见,lettuceconnectionconfiguration.class与jedisconnectionconfiguration.class当中都有一个相同的注解 @conditionalonmissingbean({redisconnectionfactory.class}),这是说,假如redisconnectionfactory这个bean已经被注册到容器里,那么与它相似的其他bean就不会再被加载注册,简单点说,对lettuceconnectionconfiguration与jedisconnectionconfiguration各自加上 @conditionalonmissingbean({redisconnectionfactory.class})注解,两者当中只能加载注册其中一个到容器里,另外一个就不会再进行加载注册。

那么,问题就来了,谁会先被注册呢?

这就回到了上面提到的一句,@import({lettuceconnectionconfiguration.class, jedisconnectionconfiguration.class})这一句里的先后顺序很关键,lettuceconnectionconfiguration在前面,就意味着,lettuceconnectionconfiguration将会被注册。

可见,springboot默认是使用lettuce来连接redis的。

当我们引入spring-boot-starter-data-redis依赖包时,其实就相当于引入lettuce包,这时就会使用lettuce驱动,若不想使用该默认的lettuce驱动,直接将lettuce依赖排除即可。

12org.springframework.boot3spring-boot-starter-data-redis456io.lettuce7lettuce-core8910

然后再引入jedis依赖——

12redis.clients3jedis4

这样,在进行redisautoconfiguration的导入注解时,因为没有找到lettuce依赖,故而这注解@import({lettuceconnectionconfiguration.class, jedisconnectionconfiguration.class})的第二个位置上的jedisconnectionconfiguration就有效了,就可以被注册到容器了,当做springboot操作redis的驱动。

lettuce与jedis两者有什么区别呢?

lettuce:底层是用netty实现,线程安全,默认只有一个实例。

jedis:可直连redis服务端,配合连接池使用,可增加物理连接。

根据异常提示找到出现错误的方法,在下列代码里的lettuceconverters.toboolean(this.getconnection().zadd(key, score, value))——

1publicbooleanzadd(byte[]key,doublescore,byte[]value){2assert.notnull(key,"keymustnotbenull!");3assert.notnull(value,"valuemustnotbenull!");45try{6if(this.ispipelined()){7this.pipeline(this.connection.newlettuceresult(this.getasyncconnection().zadd(key,score,value),lettuceconverters.longtoboolean()));8returnnull;9}elseif(this.isqueueing()){10this.transaction(this.connection.newlettuceresult(this.getasyncconnection().zadd(key,score,value),lettuceconverters.longtoboolean()));11returnnull;12}else{13returnlettuceconverters.toboolean(this.getconnection().zadd(key,score,value));14}15}catch(exceptionvar6){16throwthis.convertlettuceaccessexception(var6);17}18}

lettuceconverters.toboolean()是将long转为boolean,正常情况下,this.getconnection().zadd(key, score, value)如果新增成功话,那么返回1,这样lettuceconverters.toboolean(1)得到的是true,反之,如果新增失败,则返回0,即lettuceconverters.toboolean(0),还有第三种情况,就是这个this.getconnection().zadd(key, score, value)方法出现异常,什么情况下会出现异常呢?应该是,connection连接失败的时候。

到此,相信大家对“springboot2.x集成lettuce连接redis集群报超时异常怎么解决”有了更深的了解,不妨来实际操作一番吧!这里是恰卡编程网网站,更多相关内容可以进入相关频道进行查询,关注亚博电竞手机版,继续学习!

展开全文
内容来源于互联网和用户投稿,文章中一旦含有亚博电竞手机版的联系方式务必识别真假,本站仅做信息展示不承担任何相关责任,如有侵权或涉及法律问题请联系亚博电竞手机版删除

最新文章

网站地图