Подтвердить что ты не робот

Не удалось получить ресурс из пула (SocketTimeoutException:)

Я запускаю несколько рабочих потоков (около 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
4b9b3361

Ответ 1

Я заметил, что это исключение может и будет выбрано, если Redis не запущен. Просто голова.

Ответ 2

Если ваш код выглядит следующим образом:

JedisPoolConfig jedisPoolConfig = initPoolConfig();    
jedisPool = new JedisPool(jedisPoolConfig, "*.*.*.*", 6379);  

Вы можете попробовать следующее:

JedisPoolConfig jedisPoolConfig = initPoolConfig();    
jedisPool = new JedisPool(jedisPoolConfig, "*.*.*.*", 6379,10*1000); 

Это связано с тем, что для Redis время ожидания по умолчанию составляет 2 секунды, но программа, возможно, закончила работу в это время.

Ответ 3

На основании ответа Рика Хэнлона это исключение также выбрасывается при использовании 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

Ответ 4

Не уверен, но, возможно, вы не возвращаете объекты Jedis в пул, а ваш redis-сервер имеет ограничение на соединение.

Каждый рабочий поток должен возвращать экземпляры Jedis в пул после завершения работы:

Jedis jedis = jedisPool.getResource();
try {
    jedis.getClient().setTimeoutInfinite();
    // your code here...
    ...
} finally {
    jedisPool.returnResource(jedis);
}

Ответ 5

Случалось ли это всегда или изредка? Если это случалось, вы можете проверить размер пула подключений.

Размер пула соединений по умолчанию, если вы используете JedisPoolConfig, 8. Это может быть слишком мало для вашего дела.

JedisPoolConfig poolConfig = new JedisPoolConfig();
poolConfig.setMaxTotal(128);
jedisPool = new JedisPool(poolConfig, HOST, PORT, ...);

Ответ 6

Возможные причины;

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;     
}