Ответ 1
Я заметил, что это исключение может и будет выбрано, если Redis не запущен. Просто голова.
Я запускаю несколько рабочих потоков (около 10) для доступа к данным из redis Q.
Я использую таймаут infinte для Jedis Client.
Jedis jedis = pool.getResource();
jedis.getClient().setTimeoutInfinite();
Тем не менее я получаю сообщение об ошибке "Не удалось получить ресурс из пула". Ниже приведена таблица stacktrace.
redis.clients.jedis.exceptions.JedisConnectionException: Could not get a resource from the pool
at redis.clients.util.Pool.getResource(Pool.java:22)
at Workers.Worker1.met1(Worker1.java:124)
at Workers.Worker1.work(Worker1.java:108)
at org.gearman.impl.worker.WorkerConnectionController$3.run(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)
Caused by: redis.clients.jedis.exceptions.JedisConnectionException: java.net.SocketTimeoutException: connect timed out
at redis.clients.jedis.Connection.connect(Connection.java:124)
at redis.clients.jedis.BinaryClient.connect(BinaryClient.java:54)
at redis.clients.jedis.BinaryJedis.connect(BinaryJedis.java:1657)
at redis.clients.jedis.JedisPool$JedisFactory.makeObject(JedisPool.java:63)
at org.apache.commons.pool.impl.GenericObjectPool.borrowObject(GenericObjectPool.java:1188)
at redis.clients.util.Pool.getResource(Pool.java:20)
... 6 more
Caused by: java.net.SocketTimeoutException: connect timed out
at java.net.DualStackPlainSocketImpl.waitForConnect(Native Method)
at java.net.DualStackPlainSocketImpl.socketConnect(Unknown Source)
at java.net.AbstractPlainSocketImpl.doConnect(Unknown Source)
at java.net.AbstractPlainSocketImpl.connectToAddress(Unknown Source)
at java.net.AbstractPlainSocketImpl.connect(Unknown Source)
at java.net.PlainSocketImpl.connect(Unknown Source)
at java.net.SocksSocketImpl.connect(Unknown Source)
at java.net.Socket.connect(Unknown Source)
at redis.clients.jedis.Connection.connect(Connection.java:119)
... 11 more
Я заметил, что это исключение может и будет выбрано, если Redis не запущен. Просто голова.
Если ваш код выглядит следующим образом:
JedisPoolConfig jedisPoolConfig = initPoolConfig();
jedisPool = new JedisPool(jedisPoolConfig, "*.*.*.*", 6379);
Вы можете попробовать следующее:
JedisPoolConfig jedisPoolConfig = initPoolConfig();
jedisPool = new JedisPool(jedisPoolConfig, "*.*.*.*", 6379,10*1000);
Это связано с тем, что для Redis время ожидания по умолчанию составляет 2 секунды, но программа, возможно, закончила работу в это время.
На основании ответа Рика Хэнлона это исключение также выбрасывается при использовании Redis с Spring Boot.
Если вы используете Spring Boot, просто недостаточно для использования Redis; вам также необходимо вручную загрузить и установить Redis на вашем компьютере с redis.io, затем запустить его с терминала Bash:
[email protected]_pc:/path/to/redis/dir$ ./src/redis-server ./redis.conf
После запуска сервера вам нужно будет добавить соответствующие строки во все ваши приложения, которые используют Redis:
application.properties
:
...
spring.redis.host: <yourhost> // usually localhost, but can also be on a LAN
spring.redis.port: <yourport> // usually 6379, but settable in redis.conf
application.yml
:
...
spring:
redis:
host: <yourhost> // usually localhost, but can also be on a LAN
port: <yourport> // usually 6379, but settable in redis.conf
Не уверен, но, возможно, вы не возвращаете объекты Jedis в пул, а ваш redis-сервер имеет ограничение на соединение.
Каждый рабочий поток должен возвращать экземпляры Jedis в пул после завершения работы:
Jedis jedis = jedisPool.getResource();
try {
jedis.getClient().setTimeoutInfinite();
// your code here...
...
} finally {
jedisPool.returnResource(jedis);
}
Случалось ли это всегда или изредка? Если это случалось, вы можете проверить размер пула подключений.
Размер пула соединений по умолчанию, если вы используете JedisPoolConfig
, 8. Это может быть слишком мало для вашего дела.
JedisPoolConfig poolConfig = new JedisPoolConfig();
poolConfig.setMaxTotal(128);
jedisPool = new JedisPool(poolConfig, HOST, PORT, ...);
Возможные причины;
1 - сервер Redis не работает или приложение Redis не отвечает.
2 - Приложение не может подключиться к серверу Redis (проблемы с брандмауэром и т.д.).
3 - Превышено время ожидания подключения к серверу Redis.
4 - Все соединения в пуле (Redis) в настоящее время заняты, новое соединение не может быть выделено.
Случаи 1 и 2 связаны ниже.
В случае 3 время ожидания соединения должно быть увеличено ("RedisConnectionTimeout"):
pool = new pool(poolConfig, RedisIp, RedisPort, RedisConnectionTimeout);
Для случая 4 максимальное количество соединений должно быть увеличено ("RedisMaximumActiveConnectionCount"):
poolConfig.setMaxTotal(RedisMaximumActiveConnectionCount);
Предполагая следующую или похожую реализацию;
private Pool<Jedis> pool = null;
private final String RedisIp="10.10.10.11";
private final int RedisPort=6379;
private final String RedisConnectionTimeout=2000;
private final String RedisMaximumWaitTime=1000;
private final String RedisMaximumIdleConnectionCount=20;
private final String RedisMaximumActiveConnectionCount=300;
private final String SentinelActive=false;
private final String SentinelHostList="10.10.10.10:26379,10.10.10.10:26380,10.10.10.10:26381";
private final String SentinelMasterName="sentinel-master-name";
private synchronized void initializePool()
{
if(pool!=null) return;
poolConfig poolConfig = new poolConfig();
poolConfig.setMaxTotal(RedisMaximumActiveConnectionCount);
poolConfig.setMaxIdle(RedisMaximumIdleConnectionCount);
poolConfig.setMaxWaitMillis(RedisMaximumWaitTime);
if(SentinelActive)
{
String [] sentinelsArray = SentinelHostList.split(",");
Set<String> sentinels = new HashSet<>();
for(String sentinel : sentinelsArray)
{
sentinels.add(sentinel);
}
String masterName = SentinelMasterName;
pool = new JedisSentinelPool(masterName, sentinels, poolConfig, RedisConnectionTimeout);
}
else
{
pool = new pool(poolConfig, RedisIp, RedisPort, RedisConnectionTimeout);
}
}
protected Jedis getConnection()
{
if(pool==null)
initializePool();
Jedis jedis = pool.getResource();
return jedis;
}