记录一次排查jedis连接失败的问题
事件背景:这次不是直接使用jedis集成,而是按要求集成公司封装的工具包,配置项也是自定义的。
redis.clients.jedis.exceptions.JedisConnectionException: Could not get a resource from the pool at redis.clients.jedis.util.Pool.getResource(Pool.java:84) at redis.clients.jedis.JedisPool.getResource(JedisPool.java:370) ......此处略过几十行 at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191) at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659) at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) at java.lang.Thread.run(Thread.java:748) Caused by: redis.clients.jedis.exceptions.JedisConnectionException: Failed to create socket. at redis.clients.jedis.DefaultJedisSocketFactory.createSocket(DefaultJedisSocketFactory.java:110) at redis.clients.jedis.Connection.connect(Connection.java:226) at redis.clients.jedis.BinaryClient.connect(BinaryClient.java:140) at redis.clients.jedis.BinaryJedis.connect(BinaryJedis.java:310) at redis.clients.jedis.BinaryJedis.initializeFromClientConfig(BinaryJedis.java:88) at redis.clients.jedis.BinaryJedis.<init>(BinaryJedis.java:293) at redis.clients.jedis.Jedis.<init>(Jedis.java:169) at redis.clients.jedis.JedisFactory.makeObject(JedisFactory.java:177) at org.apache.commons.pool2.impl.GenericObjectPool.create(GenericObjectPool.java:918) at org.apache.commons.pool2.impl.GenericObjectPool.borrowObject(GenericObjectPool.java:431) at org.apache.commons.pool2.impl.GenericObjectPool.borrowObject(GenericObjectPool.java:356) at redis.clients.jedis.util.Pool.getResource(Pool.java:75) ... 72 more Caused by: java.net.SocketTimeoutException: connect timed out at java.net.DualStackPlainSocketImpl.waitForConnect(Native Method) at java.net.DualStackPlainSocketImpl.socketConnect(DualStackPlainSocketImpl.java:85) at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:350) at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:206) at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:188) at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:172) at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392) at java.net.Socket.connect(Socket.java:589) at redis.clients.jedis.DefaultJedisSocketFactory.createSocket(DefaultJedisSocketFactory.java:80) ... 83 more
第一个问题:Could not get a resource from the pool
这个问题的原因无法就这几种:
1. 参数问题,有可能是连接池太小引起
2. jedis版本问题引起
3.服务器性能引起
初步判断是Redis连接数不够用,调大了里连接参数
maxActive: 1000 maxTotal: 100 maxIdle: 100 minIdle: 50
重启项目后发现问题依然存在,翻找源码,加断点看一下 JedisPool 里到底加载了什么。
这不是初始值么,我的参数根本没起作用,又翻找加载 JedisPool 的过程源码,才发现,配置文件少了一级。原来是 **.**.pool.maxActive=20 这样的配置路径。
配置文件修改好之后,jedisPool 可以正常加载我设置的参数了,但问题依然存在。那就只能从第二个提示入手了。
第二个问题:Failed to create socket.
这个提示很好排查,就是验证你的Redis是否可以连接上。用连接工具、程序都可以尝试验证,网上有多排查此原因的方式,都是因为Redis服务器端配置的问题。
写个验证程序:
public static void main(String[] args) {
Jedis jedis = new Jedis("服务器的IP", 端口号);
System.out.println(jedis.ping());
}
第一次执行的报了异常:
Exception in thread "main" redis.clients.jedis.exceptions.JedisConnectionException: Failed to create socket.
at redis.clients.jedis.DefaultJedisSocketFactory.createSocket(DefaultJedisSocketFactory.java:110)
at redis.clients.jedis.Connection.connect(Connection.java:226)
at redis.clients.jedis.BinaryClient.connect(BinaryClient.java:140)
at redis.clients.jedis.Connection.sendCommand(Connection.java:163)
at redis.clients.jedis.Connection.sendCommand(Connection.java:158)
at redis.clients.jedis.BinaryClient.ping(BinaryClient.java:191)
at redis.clients.jedis.BinaryJedis.ping(BinaryJedis.java:379)
at com.gientech.core.core.account.Test.main(Test.java:9)
Caused by: java.net.SocketTimeoutException: connect timed out
at java.net.DualStackPlainSocketImpl.waitForConnect(Native Method)
at java.net.DualStackPlainSocketImpl.socketConnect(DualStackPlainSocketImpl.java:85)
at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:350)
at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:206)
at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:188)
at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:172)
at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392)
at java.net.Socket.connect(Socket.java:589)
at redis.clients.jedis.DefaultJedisSocketFactory.createSocket(DefaultJedisSocketFactory.java:80)
... 7 more
这就真尴尬了,再核对服务器资源文档上的Redis信息,原来服务器IP和端口是不能直接用的。需要用外网映射IP和端口。改完之后连接正常。