【问题标题】:"Cannot get Jedis connection" when using SSL with Redis and Spring Data Redis将 SSL 与 Redis 和 Spring Data Redis 一起使用时“无法获得 Jedis 连接”
【发布时间】:2018-07-07 17:11:47
【问题描述】:

我正在使用启用 SSL 的 Redis(来自 AWS 的 ElasticCache),并且很难使用 Spring Data Redis 连接到它。

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

下面是sn-p的代码:

    @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:不能 获得绝地连接;嵌套异常是 redis.clients.jedis.exceptions.JedisConnectionException:无法获取 池中的资源] 有根本原因 2018-01-22T15:59:35.531+11:00 [APP/PROC/WEB/0] [OUT] java.net.SocketException:连接重置 2018-01-22T15:59:35.531+11:00 [APP/PROC/WEB/0] [OUT] 在 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] 在 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] 在 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] 在 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] [出] 在 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] 在 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] 在 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] [出] 在 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] [出] 在 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] 在 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] [出] 在 redis.clients.jedis.JedisFactory.makeObject(JedisFactory.java:108) ~[jedis-2.9.0.jar!/:na]"

注意:

  1. 这不是 SSL 证书的问题,因为 AWS 的 SSL 证书已经存在于 JVM 信任存储中,请注意 JedisPool 正在使用 SSL。

  2. 我怀疑 JedisConnectionFactory 以某种方式忽略而不建立 SSL 连接。我尝试了 JedisConnectionFactory 的其他 arg 构造函数,例如将 useSSL 设置为 true 等,但没有运气。

感谢任何帮助或指点。

【问题讨论】:

  • 不应该是redisHost + ":"+ redisPort吗?
  • 是的,很抱歉,这是我发布代码时的拼写错误。 String hostUri = "redis://:" + redisPassword + "@" + redisHost + ":" + redisPort;
  • 是否有人对上述问题有任何指示。我怀疑这是 Spring Data Redis 中的错误?

标签: spring ssl redis


【解决方案1】:

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

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

【讨论】:

  • 我也尝试了上述方法,但没有运气。对于上述情况,我也遇到了同样的例外情况。
  • 你使用哪个版本的 Spring Data Redis?
  • 我使用了 1.5.9.RELEASE 的 Spring Boot(和 Spring Data Redis)。我也试过 1.5.6.Release 导致同样的问题。
【解决方案2】:

不过,我遇到了类似的问题,它与 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。

【讨论】:

    【解决方案3】:

    您只提到了 AWS Elastic Redis,但没有具体说明是基于集群的 Redis 还是单节点 Redis?

    Spring Data Redis 2.2 将支持使用 SSL 的集群。 https://jira.spring.io/browse/DATAREDIS-974

    【讨论】:

      【解决方案4】:

      对于redis client 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 等。

      【讨论】:

        猜你喜欢
        • 2018-11-04
        • 2016-10-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-01-01
        • 2022-08-03
        • 2020-07-27
        • 2018-10-11
        相关资源
        最近更新 更多