0、问题描述
使用Jedis
连接redis
进行数据查询操作,正常的代码运行没有问题,但是时不时会报出如下错误:
1 | Exception in thread "main" redis.clients.jedis.exceptions.JedisConnectionException: java.net.SocketTimeoutException: Read timed out |
究其原因,可以定位为java.net.SocketTimeoutException: Read timed out
,即网络连接异常;
1、 可能的原因
1.1 服务器资源包括内存、磁盘、cpu等利用率高
经过查看redis
部署机器的状态信息,发现整体机器运行状态良好
1.2 服务器设置防火墙,导致连接失败
因为正常的代码流程都可以跑通,所以防火墙设置没有问题;
1.3 redis
配置文件bind
监听host
配置不当
redis
的配置文件中bind
对应host
的配置如下:
1 | # By default Redis listens for connections from all the network interfaces |
默认的bind
绑定的host
为0.0.0.0
,即可以监听每一个可用的网络接口;相当于配置为:
1 | bind 0.0.0.0 |
我们的配置文件也配置正常,而且正常的代码流程运行正常,也可以佐证这一点;
1.4 Jedis
使用配置问题
目前Jedis
的连接池配置如下:
1 | private static JedisPool getPool() { |
构建JedisPool
的逻辑中,只是设置了config.setMaxWait(1000 * 200000);
,这个是引入新的jedis
实例的最大等待时间,并没有进行其他相关的连接超时的配置;于是查看JedisPool
的源代码,发现如下:
1 | public JedisPool(final Config poolConfig, final String host) { |
由上述代码可以看到,JedisPool
有多个重载的构造函数,并且构造函数中需要传入一个timeout
参数作为连接的超时时间,如果没有传,则采用Protocol.DEFAULT_TIMEOUT
作为默认的超时时间,继续跟踪源码:
1 | public final class Protocol { |
可以得出结论,默认JedisPool
中连接的默认超时时间为2秒,而我们调用的JedisPool
构造函数,恰恰采用的是这个配置,只要两秒钟没有连接成功,redis的连接就断开,从而报错,这在数据库请求并发量比较大的时候是有可能发生的,遂做如下更改,在创建JedisPool
的时候,传入一个较大的超时时间:
1 | pool = new JedisPool(config, ParamUtil.REDIS_ADDRESS[0], ParamUtil.REDIS_PORT, 1000 * 10); |
2、总结
遇到问题还是多查,多看源码,多看源码中的配置,仔细一项一项地排查问题!