这次我接收了一个活动项目,由于之前有个活动类型和我这个基本一致,所以直接copy的上一份活动。
上次活动为了提高并发能力,所以数据都存储在redis,等活动结束手动入mysql。
压测工具使用jemeter
线程数30,压100s,qps在300多
但是异常率很高
排查服务日志,疯狂刷一个错误:
lettuce连接异常:
Cannot assign requested address (Address not available)
lettuce不是redis的一个新连接池吗?
于是chatgpt问答一番,得知springboot2.1之后redis默认使用lettuce连接池。
当时也没有在意redis配置,因为redis肯定是连接上了,很多请求正常返回了。
于是查看服务器TCP连接情况,一看我去30000多个TIME_WAIT,能用的端口基本用完。
百度了一番给服务扩了端口和TIME_WAIT复用,心想着这事就算解决了。
没想到再跑一次压测还是报错了,端口还是30000多个TIME_WAIT。
感觉不是端口的问题,治标不治本。
最后好几个同事一起看配置,发现我们的redis连接配置是生效的,但是redis连接池的配置是无效的!
spring.redis.pool.maxIdle=300
spring.redis.pool.minIdle=300
spring.redis.pool.max-wait=500
spring.redis.pool.max-active=1000
正确的配置应该是:
spring.redis.lettuce.pool.maxIdle=300
spring.redis.lettuce.pool.minIdle=300
spring.redis.lettuce.pool.max-wait=500
spring.redis.lettuce.pool.max-active=1000
为什么呢!因为springboot2.1之后,lettuce成了redis默认连接池,于是乎之前的jedis连接池配置就失效了,记一下这个坑希望能帮到更多的朋友,可能springboot-redis的开发觉得能用到高并发的肯定会优化这个参数,进而发现旧连接池的配置是无效的,好吧,竟然没有兼容老配置。
至于为什么lettuce默认的连接池配置顶不住高并发呢?这个就和连接池的策略有关系了,可能是因为连接池达到最大活跃后,后续的线程拿不到新的redis连接,且超过max-wait时间,所以抛出了异常。具体配置的解释如下: