redis / jedis

Redis Java client

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Resource leak: JedisPooled does not return connection to the pool on socket exception

chochos opened this issue · comments

JedisPooled is very convenient because you can just issue commands without having to do a try-with-resources for every call.

When using a pipeline, try-with-resources is still necessary. But, if a socket exception occurs, the pipe is closed but the connection is not returned to the pool, so with enough exceptions, the pool is exhausted.

To reproduce, I ran a local redis server and then ran this Groovy script:

import redis.clients.jedis.JedisPooled

var pool = new org.apache.commons.pool2.impl.GenericObjectPoolConfig<redis.clients.jedis.Connection>()
pool.maxTotal=4
pool.maxWait=java.time.Duration.ofMillis(200)

def redis = new JedisPooled(pool, 'localhost', 6379)
def log = org.slf4j.LoggerFactory.getLogger("demo")

while (true) {
    try (var pipe = redis.pipelined()) {
        println pipe.smembers('currencies')
        println "POOL max ${redis.pool.maxTotal} active ${redis.pool.numActive}"
    } catch (RuntimeException ex) {
        log.error("oops, something went wrong", ex)
        println "POOL max ${redis.pool.maxTotal} active ${redis.pool.numActive}"
    }
    Thread.sleep(2000)
}

This will print active connections as 1. Then stop the server, and let the script show an exception; start the server again, and now it will display active connections as 2; you can repeat this until the pool is exhausted and the error changes from JedisConnectionException saying "unexpected end of stream" to a JedisException caused by a NoSuchElementException thrown by the pool.

I have managed to avoid this by enabling borrowOnTrue setting on the pool, but this causes some overhead which is undesirable. I believe the JedisPooled should catch the socket exceptions and discard the connection so the pool can create a new one when needed.

@chochos Thank you for raising this.

Hopefully it is fixed. You can find the fix in Jedis 5.2.0-SNAPSHOT shortly.