在使用 SSL 与 Redis 和 Spring Data Redis 时出现“无法获取 Jedis 连接”的问题

7

我正在使用启用SSL的Redis(来自AWS的ElasticCache),在使用Spring Data Redis连接时遇到了一些困难。

请注意,如果我使用纯Jedis或带有Spring的Jedis Pool,则连接正常工作。

以下是代码片段:

    @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使用方法:

    @Autowired
    private RedisTemplate<String, String> redistemplate;


    public void api2() {

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

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

}

任何使用RedisTemplate的操作都会抛出以下异常:
嵌套异常是org.springframework.data.redis.RedisConnectionFailureException:无法获取Jedis连接;嵌套异常是redis.clients.jedis.exceptions.JedisConnectionException:无法从池中获取资源],根本原因是java.net.SocketException:连接重置。在SocketInputStream.read(SocketInputStream.java:210)处读取,在SocketInputStream.read(SocketInputStream.java:141)处读取,在SocketInputStream.read(SocketInputStream.java:127)处读取,在redis.clients.util.RedisInputStream.ensureFill(RedisInputStream.java:196)处填充,以确保填充,redis.clients.util.RedisInputStream.readByte(RedisInputStream.java:40),redis.clients.jedis.Protocol.process(Protocol.java:151),redis.clients.jedis.Protocol.read(Protocol.java:215),redis.clients.jedis.Connection.readProtocolWithCheckingBroken(Connection.java:340),redis.clients.jedis.Connection.getStatusCodeReply(Connection.java:239),redis.clients.jedis.BinaryJedis.auth(BinaryJedis.java:2139),redis.clients.jedis.JedisFactory.makeObject(JedisFactory.java:108)。
注意:
  1. 这不是SSL证书的问题,因为AWS的SSL证书已经存在于JVM信任库中,而且请注意JedisPool正在使用SSL。

  2. 我怀疑JedisConnectionFactory在忽略并且没有建立SSL连接。我尝试使用JedisConnectionFactory的其他arg构造函数,例如将useSSL设置为true等,但都没有成功。

希望能提供任何帮助或者指引。


应该是 redisHost + ":"+ redisPort 吧? - user7294900
是的,抱歉,在发布我的代码时出现了一个打字错误。String hostUri = "rediss://:" + redisPassword + "@" + redisHost + ":" + redisPort; - Raghuveer Bhandarkar
有人对上述问题有什么指点吗?我怀疑这可能是Spring Data Redis中的一个错误? - Raghuveer Bhandarkar
4个回答

0

不要使用JedisShardInfo,因为它会导致配置上的歧义。在Spring Data Redis 2.0中,接受JedisShardInfo的构造函数已被弃用。请改用基于属性的配置:

JedisConnectionFactory conn =  new JedisConnectionFactory();
conn.setHostName(redisHost);
conn.setPort(redisPort);
conn.setUseSsl(true);

我也尝试了上述方法,但没有成功。对于上述内容,我仍然得到相同的异常。 - Raghuveer Bhandarkar
你使用的 Spring Data Redis 版本是哪个? - mp911de
我使用了Spring Boot的1.5.9.RELEASE版本(以及Spring Data Redis)。我尝试过1.5.6.Release版本,但问题仍然存在。 - Raghuveer Bhandarkar

0

我遇到了类似的问题,但是它与JedisPool有关,而不是与SpringJedisShardInfo有关。我相信这本质上是相同的问题。当连接启用SSL的AWS Elasticache redis集群时,我会遇到一个

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

解决我的问题的方法是使用jedis 2.9.0并像这样初始化我的JedisPool
String host = "someHost"; // The primary endpoint of the cluster
JedisPool jedisPool = new JedisPool("rediss://" + host + ":6379");

在这里使用String构造函数很重要,因为URI构造函数不支持SSL。


0

对于 redis客户端3.2.0 及以上版本,我们可以按照以下方式设置ssl属性:

使用JedisShardInfo:

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

使用JedisPool:

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

poolConfig中,您可以指定各种属性,例如setMaxIdlesetMaxWaitMillissetMaxTotal等。

0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接