"Cannot get Jedis connection" when using SSL with Redis and Spring Data Redis
Asked Answered
W

4

7

I'm using SSL enabled Redis (ElasticCache from AWS), and having difficulty in connecting to it using Spring Data Redis.

(Note that the connectivity works fine, if I use plain Jedis or Jedis Pool with Spring).

Following is the code snippet:

    @Value("${vcap.services.myredis.credentials.host}")
    private String redisHost;

    @Value("${vcap.services.myredis.credentials.password}")
    private String redisPassword;

    @Value("${vcap.services.myredis.credentials.port}")
    private String redisPort;

    public RedisTemplate<String, Object> redisTemplate() {

        final RedisTemplate<String, Object> template = new RedisTemplate<String, Object>();


        String hostUri = "rediss://:" + redisPassword + "@" + redisHost + redisPort;    

        JedisShardInfo info = new JedisShardInfo(hostUri);

        JedisConnectionFactory conn =  new JedisConnectionFactory(info);

        conn.afterPropertiesSet();

        template.setConnectionFactory(conn);
        template.setValueSerializer(new GenericToStringSerializer<Object>(Object.class));
        return template;
    }

}

RedisTemplate usage:

    @Autowired
    private RedisTemplate<String, String> redistemplate;


    public void api2() {

        HashOperations<String, Object, Object> hashOperations = redistemplate.opsForHash();

        hashOperations.put("KEY", "1", "one"); 
    }

}

Any operation using RedisTemplate throws below exception:

"nested exception is org.springframework.data.redis.RedisConnectionFailureException: Cannot get Jedis connection; nested exception is redis.clients.jedis.exceptions.JedisConnectionException: Could not get a resource from the pool] with root cause 2018-01-22T15:59:35.531+11:00 [APP/PROC/WEB/0] [OUT] java.net.SocketException: Connection reset 2018-01-22T15:59:35.531+11:00 [APP/PROC/WEB/0] [OUT] at java.net.SocketInputStream.read(SocketInputStream.java:210) ~[na:1.8.0_141] 2018-01-22T15:59:35.531+11:00 [APP/PROC/WEB/0] [OUT] at java.net.SocketInputStream.read(SocketInputStream.java:141) ~[na:1.8.0_141] 2018-01-22T15:59:35.531+11:00 [APP/PROC/WEB/0] [OUT] at java.net.SocketInputStream.read(SocketInputStream.java:127) ~[na:1.8.0_141] 2018-01-22T15:59:35.531+11:00 [APP/PROC/WEB/0] [OUT] at redis.clients.util.RedisInputStream.ensureFill(RedisInputStream.java:196) ~[jedis-2.9.0.jar!/:na] 2018-01-22T15:59:35.531+11:00 [APP/PROC/WEB/0] [OUT] at redis.clients.util.RedisInputStream.readByte(RedisInputStream.java:40) ~[jedis-2.9.0.jar!/:na] 2018-01-22T15:59:35.531+11:00 [APP/PROC/WEB/0] [OUT] at redis.clients.jedis.Protocol.process(Protocol.java:151) ~[jedis-2.9.0.jar!/:na] 2018-01-22T15:59:35.531+11:00 [APP/PROC/WEB/0] [OUT] at redis.clients.jedis.Protocol.read(Protocol.java:215) ~[jedis-2.9.0.jar!/:na] 2018-01-22T15:59:35.531+11:00 [APP/PROC/WEB/0] [OUT] at redis.clients.jedis.Connection.readProtocolWithCheckingBroken(Connection.java:340) ~[jedis-2.9.0.jar!/:na] 2018-01-22T15:59:35.531+11:00 [APP/PROC/WEB/0] [OUT] at redis.clients.jedis.Connection.getStatusCodeReply(Connection.java:239) ~[jedis-2.9.0.jar!/:na] 2018-01-22T15:59:35.531+11:00 [APP/PROC/WEB/0] [OUT] at redis.clients.jedis.BinaryJedis.auth(BinaryJedis.java:2139) ~[jedis-2.9.0.jar!/:na] 2018-01-22T15:59:35.531+11:00 [APP/PROC/WEB/0] [OUT] at redis.clients.jedis.JedisFactory.makeObject(JedisFactory.java:108) ~[jedis-2.9.0.jar!/:na]"

Note:

  1. This is not an issue with SSL Certs as SSL certs for AWS are already present in the JVM Trust store and note that JedisPool is working with SSL.

  2. I suspect that somehow the JedisConnectionFactory is ignoring and not making a SSL connection. I tried other arg constructors of JedisConnectionFactory like setting the useSSL to true, etc, without luck.

Any help or pointers are appreciated.

Wonderment answered 29/1, 2018 at 3:26 Comment(3)
Shouldn't it be redisHost + ":"+ redisPort?Phio
Yes, apologies, that is a typo while posting my code.. String hostUri = "rediss://:" + redisPassword + "@" + redisHost + ":" + redisPort;Wonderment
Does anyone have any pointers to this the above issue.. I suspect this to be a bug in Spring Data Redis?Wonderment
S
0

Do not use JedisShardInfo as it causes ambiguities with the configuration it carries. The constructor accepting JedisShardInfo is deprecated in Spring Data Redis 2.0. Use the property-based configuration instead:

JedisConnectionFactory conn =  new JedisConnectionFactory();
conn.setHostName(redisHost);
conn.setPort(redisPort);
conn.setUseSsl(true);
Szombathely answered 31/1, 2018 at 10:28 Comment(3)
I tried the above as well without luck. I'm getting same exception for the above as well.Wonderment
Which version of Spring Data Redis do you use?Szombathely
I used 1.5.9.RELEASE of Spring Boot (and Spring Data Redis). I have tried 1.5.6.Release as well resulting in same issue.Wonderment
D
0

I encountered a similar issue however, it was with JedisPool and not with Spring and JedisShardInfo. I believe though, that it is essentially the same issue. When connecting to an AWS Elasticache redis cluster with SSL enabled I would get a

redis.clients.jedis.exceptions.JedisConnectionException: java.net.SocketException: Connection reset

What solved my issue was using jedis 2.9.0 and initiating my JedisPool like this:

String host = "someHost"; // The primary endpoint of the cluster
JedisPool jedisPool = new JedisPool("rediss://" + host + ":6379");

It's important to use a String constructor here as the URI one doesn't enable SSL.

Dmitri answered 20/2, 2018 at 15:41 Comment(0)
J
0

You mentioned only AWS Elastic Redis, but you didn't specify whether it is Cluster based Redis or Single Node Redis ?

Spring Data Redis 2.2 will support for Cluster with SSL. https://jira.spring.io/browse/DATAREDIS-974

Jessiajessica answered 13/9, 2019 at 21:45 Comment(0)
F
0

For redis client 3.2.0 and above we can set ssl properties as follows:

Using JedisShardInfo:

JedisShardInfo shardInfo = new JedisShardInfo(redisServer, redisServerPort, redisTimeout, redisSsl);
shardInfo.setPassword(redisPassword);
Jedis jedis = new Jedis(shardInfo);

Using JedisPool:

jedisPool = new JedisPool(poolConfig, redisServer, redisServerPort, redisTimeout, redisPassword, redisSsl);
jedis = jedisPool.getResource();

Where, in poolConfig, you can specify various properties like, setMaxIdle, setMaxWaitMillis, setMaxTotal and so on.

Flaviaflavian answered 2/3, 2022 at 4:16 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.