redis: jedis连接超时(需要手动注入连接超时检测的配置)

news2025/1/17 3:55:51

相关版本说明

服务端:
redis_version: 6.2.8

客户端:
springBoot: 2.7.7
jedis: 3.8.0

问题

偶发redis连接超时,刷新就又好了,服务日志错误信息如下:

JedisConnectionException: Unexpected end of stream.

原因

服务端连接已超时,但是客户端不知道,去使用时就会报错;

排查

redis服务端配置查看:

# 直接查看配置文件(默认为0,单位:秒, 0表示不设置超时时间):
[root@vm bin]# cat ./redis.conf | grep timeout
timeout 600

# 登录客户端查看当前配置(单位:秒)
127.0.0.1:6379> config get timeout
1) "timeout"
2) "600"

发现服务端设置了连接超时时间为10分钟。

redis默认是不设置超时时间的,也就是 timeout 0
可能是考虑到这样就有可能导致连接回收不及时,最后连接数不够用;
所以项目上设置了10分钟超时,但是没考虑到客户端,所以就出现上面这个偶发的现象了;

解决方案

方案1、redis保持默认配置,不设置超时时间,然后最大连接数设置大一些;
方案2、redis客户端配置一下连接是否超时的检测;

方案1比较简单,直接修改配置就行,但是项目上既然要配置超时时间,那只能看看方案2了。

方案二具体配置

需要手动注入,新增配置类

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.data.redis.JedisClientConfigurationBuilderCustomizer;
import org.springframework.boot.autoconfigure.data.redis.RedisProperties;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.jedis.JedisClientConfiguration;
import org.springframework.util.ClassUtils;
import redis.clients.jedis.JedisPoolConfig;

import java.time.Duration;

@Configuration
public class JedisPoolConfiguration implements JedisClientConfigurationBuilderCustomizer {

    @Autowired
    private RedisProperties properties;

    private static final boolean COMMONS_POOL2_AVAILABLE = ClassUtils.isPresent("org.apache.commons.pool2.ObjectPool",
            JedisPoolConfiguration.class.getClassLoader());

    /**
     * 连接的最小空闲时间,达到此值后空闲连接将被移除, 默认:30分钟
     */
    @Value(value = "${spring.redis.jedis.pool.minEvictableIdleTime:30M}")
    private Duration minEvictableIdleTime;
    /**
     * 做空闲连接检测时,每次的采样数,默认每次只检测3个
     */
    @Value(value = "${spring.redis.jedis.pool.numTestsPerEvictionRun:3}")
    private int numTestsPerEvictionRun;
    /**
     * 从连接池获取连接时是否先检测(ping),每次执行命令多执行一次ping, 默认:false
     */
    @Value(value = "${spring.redis.jedis.pool.testOnBorrow:false}")
    private boolean testOnBorrow;

    @Override
    public void customize(JedisClientConfiguration.JedisClientConfigurationBuilder clientConfigurationBuilder) {
        RedisProperties.Pool pool = properties.getJedis().getPool();
        if (isPoolEnabled(pool)) {
            applyPooling(pool, clientConfigurationBuilder);
        }
    }

    private void applyPooling(RedisProperties.Pool pool,
                              JedisClientConfiguration.JedisClientConfigurationBuilder builder) {
        builder.usePooling().poolConfig(jedisPoolConfig(pool));
    }

    private JedisPoolConfig jedisPoolConfig(RedisProperties.Pool pool) {
        JedisPoolConfig config = new JedisPoolConfig();
        config.setMaxTotal(pool.getMaxActive());
        config.setMaxIdle(pool.getMaxIdle());
        config.setMinIdle(pool.getMinIdle());
        if (pool.getTimeBetweenEvictionRuns() != null) {
            config.setTimeBetweenEvictionRuns(pool.getTimeBetweenEvictionRuns());
        }
        if (pool.getMaxWait() != null) {
            config.setMaxWait(pool.getMaxWait());
        }
        if (minEvictableIdleTime != null){
            config.setMinEvictableIdleTime(minEvictableIdleTime);
        }
        config.setNumTestsPerEvictionRun(numTestsPerEvictionRun);
        config.setTestOnBorrow(testOnBorrow);
        return config;
    }


    protected boolean isPoolEnabled(RedisProperties.Pool pool) {
        Boolean enabled = pool.getEnabled();
        return (enabled != null) ? enabled : COMMONS_POOL2_AVAILABLE;
    }
}

配置文件增加如下配置

spring:
  redis:
    jedis:
      pool:
        # 从连接池获取连接时是否先检测(ping),每次执行命令多执行一次ping
        testOnBorrow: true
        # 多长时间检测一次(-1表示不进行定时检测)
        timeBetweenEvictionRuns: 30S
        # 连接的最小空闲时间,达到此值后空闲连接将被移除, 默认30分钟
        minEvictableIdleTime: 5M
        # 做空闲连接检测时,每次的采样数,默认每次只检测3个
        numTestsPerEvictionRun: 3
  • 其实只需要配置testOnBorrow=true就可以,但是如果发现失效连接,则又要去重新获取一个连接,可能会费时一点;
  • 所以还可以配置主动检测:定时去检测连接的配置,可以根据自己项目的实际超时时间,和连接数,在超时之前可以把所有连接都扫描检测到即可
    (这里是我个人的配置,仅供参考)

至此,问题已得到解决,但为什么不能直接通过配置文件自动注入呢?感兴趣的小伙伴可以继续看看以下内容:

说明

  • 因为spring-boot-autoconfigure中,不支持这三个配置:
testOnBorrow
minEvictableIdleTime
numTestsPerEvictionRun
  • 详细可以查看源码:
    org.springframework.boot.autoconfigure.data.redis.RedisProperties.Pool
    在这里插入图片描述
    org.springframework.boot.autoconfigure.data.redis.JedisConnectionConfiguration#jedisPoolConfig
    在这里插入图片描述
  • 所以可以把源码复制出来,自己修改一下
    在这里插入图片描述
  • 该问题已经反馈给spring-boot:
    spring-projects/spring-boot/issues/33814

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/158782.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Linux利用httpd搭建局域网yum源

本例环境:vmwareworkstation16 proCentOS7.9 mast节点:192.168.195.110 用于配置httpd并发布本地yum源 node节点:192.168.195.111 用于验证mast节点的yum源是否可用 思路:1.在mast节点挂载/上传镜像后配置本地yum源 2.利用本…

JSP三种脚本

脚本可以编写Java语句、变量、方法或表达式。 1.普通脚本 语法: <% Java代码%> <% page contentType"text/html;charsetUTF-8" language"java" %><html><head> <title>Title</title></head><body>&l…

对u盘的分区进行删除和格式化

一、说明 当usb盘&#xff0c;或者SD卡用作启动盘后&#xff0c;将出现多个盘符、多个分区&#xff1b;若将此盘重新当文件盘&#xff0c;需要删除以前的分区&#xff0c;并重新格式化后&#xff0c;才能使用。 二、使用Diskpart在Windows 10中对USB进行分区删除 2.1 尝试磁盘…

重启之后,台式机网络不能连接怎么办

目录 1.问题 2.排查过程 3.心得 1.问题 前天电脑意外断电后,再启动发现网络变成了未连接状态.查看本地连接显示已启动,但IPv4和IPv6未连接.当时做了一些尝试,没有收到效果,直到今天问题才得以解决. 2.排查过程 Windows网络诊断为:DNS服务器未响应.后来花了一部分时间在DNS…

ruoyi-vue集成magic-api(一)

ruoyi虽然带了强大的代码生成器&#xff0c;面对比较通用的CRUD还是游刃有余的&#xff0c;但在项目开发阶段&#xff0c;需求总是经常变化的&#xff0c;数据结构和逻辑也经常变化&#xff0c;我们需要的是快速验证功能逻辑&#xff0c;代码生成器可帮不上忙&#xff0c;每次需…

一、java编写登录功能

java编写登录功能 文章目录java编写登录功能前言编程学习记录一、登录逻辑简述二、代码实现1.创建USER表2.前端代码3.创建User类4.创建LoginServlet类5.创建JDBCUtils类6.创建UserDao类7.创建FailServlet类9.创建SuccessServlet 类11.配置tomcat 服务12.启动服务前言 编程学习…

SpringCloud Netfllix复习之Hystrix

文章目录写作背景Hystrix是什么Hystrix的核心功能上手实战RestTemplate整合HystrixOpenFeign整合HystrixOpenFeign与Hystrix整合的各种参数如何配置&#xff1f;源码验证基于HystrixCommand注解实现熔断源码分析初始化资源线程池的源码OpenFeign与Hystrix整合执行请求的源码写作…

Java多线程:创建多线程的“四种“ 方式

Java多线程&#xff1a;创建多线程的"四种" 方式 每博一文案 白马笑西风写道&#xff1a;江南有杨柳&#xff0c;有燕子&#xff0c;金鱼......汉人中有的是英俊勇武的少年&#xff0c;倜傥潇洒的少年...... 但这个美丽的姑娘就像故高昌国人那样固执&#xff1a;&qu…

buctoj-2023寒假集训-进阶训练赛(八)

问题 A: 分离出整数n从右边数第k个数字&#xff0c;递归实现 题目描述 在程序中定义一函数digit(n,k)&#xff0c;它能分离出整数n从右边数第k个数字。 输入 正整数n和k。 输出 第k个数字(若不存在则输出0&#xff09; 样例输入 31859 3 样例输出 8 #include<bits/stdc.h&g…

电商直播小程序核心功能有哪些?电商直播小程序代码分析

一个优质的电商直播小程序&#xff0c;必须带有后台管理&#xff0c;模块功能分工明确&#xff0c;可以让商家及时管理商品。在管理后台端又分为会员、商品、订单、店铺、直播、分销、优惠券、物流、数据等功能列表栏&#xff0c;基本功能较完善。下文小编将为大家讲解一下电商…

Linux命令行中 git 的使用

文章目录&#xff1a;什么是gitgitee新建仓库git提交代码1.同步远程仓库代码 - git pull2.查看本地仓库的状态 - git status3.添加代码到本地.git缓冲区 - git add4.推送代码到本地仓库.git中 - git commit5.同步本地仓库.git的内容到远程仓库 - git push什么是git Git 是一个…

2023年了,浏览器竟然还有新玩法,能看热搜能领券

在移动互联网时代&#xff0c;手机浏览器是手机中不可缺少的APP之一。我们经常使用手机浏览器查资料&#xff0c;看新闻&#xff0c;看小说等等。如今&#xff0c;手机浏览器的功能越来越强大&#xff0c;玩法也越来越多。最近&#xff0c;发现一款手机浏览器&#xff0c;竟然聚…

立创EDA入门3 通过51单片机最小板学习PCB设计

立创EDA入门3 通过51单片机最小板学习PCB设计一、本文目的二、原理图设计1. 新建工程&#xff0c;命名为51系统2. 各模块原理图3. 一些常用操作&#xff08;1&#xff09;放置普通元器件&#xff08;2&#xff09;封装、标签设置&#xff08;3&#xff09;在线库中查找元器件&a…

硬件系统工程师宝典(4)-----传输过程的信号要如何描述?

各位同学大家好&#xff0c;欢迎继续做客电子工程学习圈&#xff0c;今天我们继续来讲这本书&#xff0c;硬件系统工程师宝典。上篇我们说到为实现信号的有效传输&#xff0c;需要保证信号波形的完整和信号时序的完整&#xff0c;并且知道了从时域、频域两个角度去分析信号。那…

高压功率放大器在诱发肌电运动阈值对比研究中的应用

实验名称&#xff1a;经颅磁声刺激与经颅超声刺激诱发肌电运动阈值的对比研究 研究方向&#xff1a;生物医学 测试目的&#xff1a; 在脑科学与神经科学研究中&#xff0c;物理刺激是目前应用最广泛的电磁刺激技术。该技术利用变化的磁场诱发感应电流进而对神经组织进行调控&am…

递归算法实例应用(一)

递归算法实例应用&#xff08;一&#xff09; 递归简笔 递归和普通函数调用一样&#xff0c;都是通过函数栈实现。 以斐波那契数列递归调用为例 递归时函数调用栈的进栈、出栈过程可以由上述图示直观的体现出来&#xff0c; 因此可以得出递归的几个作用&#xff1a; ​ …

玩转CodeQLpy之代码审计实战案例

0x01 背景介绍CodeQLpy是一款半自动化的代码审计工具&#xff0c;能有效提高代码审计的效率&#xff0c;目前项目仍处于测试阶段。项目地址https://github.com/webraybtl/CodeQLpy&#xff0c;在github主页有对应的安装和使用介绍&#xff0c;如图1.1所示。-t: 指定待扫描的源码…

SignalR在Asp.NetCore的使用入门

SignalR在ASP.NET CORE下的使用 SignalR是微软提供的实时Web通信的库&#xff0c; 它会自己根据情况使用不同的链接方式&#xff0c;主要有 WebSocketlong pollingForever frameSever Events Sent 等方式&#xff0c;故可以不管其具体的实现方式&#xff0c;差不多等于开箱…

Docker部署 Oracle12c

Docker部署 Oracle12c Docker部署 registry Docker搭建 svn Docker部署 Harbor Docker 部署SQL Server 2017 Docker 安装 MS SqlServer Docker部署 Oracle12c 文章目录Docker部署 Oracle12c部署步骤1.查询oracle镜像2.下载镜像3.创建容器4.进入容器5.连接oracle数据库部署步骤…

Unreal动态多播委托

相对于普通多播委托,动态多播委托可以在蓝图中绑定事件。在这里记录一下它的使用方式:定义动态多播委托类型:声明委托变量:绑定函数:通过Add绑定:需要定义FScriptDelegate变量:为FScriptDelegate添加绑定函数这种方法的好处是可以针对单个函数进行解绑:通过AddDynamic标记宏绑定…