【发布时间】:2019-09-18 16:39:22
【问题描述】:
我正在尝试使用 Spring Data Redis + Jedis 组合连接到 AWS ElastiCache Redis。 [Redis Cluster 启用,所以它有 Cluster Config 端点,有 3 个 shard - 每个 shard 有 1 个主节点 + 2 个副本节点]
我收到读取超时错误。
Caused by: redis.clients.jedis.exceptions.JedisConnectionException: java.net.SocketTimeoutException: Read timed out
AWS Redis 服务器版本:5.0.3 / 集群模式:启用/ SSL:启用/ 身份验证:启用(通过密码)
图书馆 -- Spring-data-redis:2.1.6.Release / 绝地:2.9.0
Telnet 适用于 AWS Redis 所有节点和集群配置端点的 6379 个端口。
我自己尝试了 Redisson,它连接到 AWS Redis,没有任何问题。
所以,Redis 本身没有问题,Spring Data Redis 与 Jedis 结合会出现问题。
我的代码看起来像这样 -
RedisClusterConfiguration redisClusterConfiguration = new RedisClusterConfiguration();
redisClusterConfiguration.setClusterNodes(listOfRedisNode);
redisClusterConfiguration.setPassword(passwordString);
JedisClientConfiguration.JedisClientConfigurationBuilder jedisClientConfiguration = JedisClientConfiguration.builder();
jedisClientConfiguration.connectTimeout(Duration.ofSeconds(60));
jedisClientConfiguration.useSsl();
jedisClientConfiguration.usePooling();
JedisConnectionFactory jedisConnectionFactory = new JedisConnectionFactory(redisClusterConfiguration, jedisClientConfiguration.build() );
jedisConnectionFactory.afterPropertiesSet();
final RedisTemplate<String, Serializable> redisTemplate = new RedisTemplate<>();
redisTemplate.setConnectionFactory(jedisConnectionFactory);
redisTemplate.setKeySerializer(new JdkSerializationRedisSerializer());
redisTemplate.setValueSerializer(new JdkSerializationRedisSerializer());
redisTemplate.afterPropertiesSet();
System.out.println(redisTemplate.getClientList().size());
StringRedisConnection stringRedisConnectionlettuce = new DefaultStringRedisConnection(redisTemplate.getConnectionFactory().getConnection());
final String message2 = stringRedisConnectionlettuce.echo("Hello");
System.out.println("Hello".equals(message2));
读取超时错误 -
Exception in thread "main" java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.boot.loader.MainMethodRunner.run(MainMethodRunner.java:48)
at org.springframework.boot.loader.Launcher.launch(Launcher.java:87)
at org.springframework.boot.loader.Launcher.launch(Launcher.java:50)
at org.springframework.boot.loader.JarLauncher.main(JarLauncher.java:51)
Caused by: redis.clients.jedis.exceptions.JedisConnectionException: java.net.SocketTimeoutException: Read timed out
at redis.clients.util.RedisInputStream.ensureFill(RedisInputStream.java:202)
at redis.clients.util.RedisInputStream.readByte(RedisInputStream.java:40)
at redis.clients.jedis.Protocol.process(Protocol.java:151)
at redis.clients.jedis.Protocol.read(Protocol.java:215)
at redis.clients.jedis.Connection.readProtocolWithCheckingBroken(Connection.java:340)
at redis.clients.jedis.Connection.getStatusCodeReply(Connection.java:239)
at redis.clients.jedis.BinaryClient.connect(BinaryClient.java:96)
at redis.clients.jedis.Connection.sendCommand(Connection.java:126)
at redis.clients.jedis.Connection.sendCommand(Connection.java:117)
at redis.clients.jedis.BinaryClient.auth(BinaryClient.java:564)
at redis.clients.jedis.BinaryJedis.auth(BinaryJedis.java:2138)
at redis.clients.jedis.JedisClusterConnectionHandler.initializeSlotsCache(JedisClusterConnectionHandler.java:36)
at redis.clients.jedis.JedisClusterConnectionHandler.<init>(JedisClusterConnectionHandler.java:17)
at redis.clients.jedis.JedisSlotBasedConnectionHandler.<init>(JedisSlotBasedConnectionHandler.java:24)
at redis.clients.jedis.BinaryJedisCluster.<init>(BinaryJedisCluster.java:54)
at redis.clients.jedis.JedisCluster.<init>(JedisCluster.java:93)
at org.springframework.data.redis.connection.jedis.JedisConnectionFactory.createCluster(JedisConnectionFactory.java:418)
at org.springframework.data.redis.connection.jedis.JedisConnectionFactory.createCluster(JedisConnectionFactory.java:388)
at org.springframework.data.redis.connection.jedis.JedisConnectionFactory.afterPropertiesSet(JedisConnectionFactory.java:345)
at io.github.deepshiv126.springdataredis.example.MySpringBootApplication.main(MySpringBootApplication.java:306)
... 8 more
Caused by: java.net.SocketTimeoutException: Read timed out
at java.net.SocketInputStream.socketRead0(Native Method)
at java.net.SocketInputStream.socketRead(SocketInputStream.java:116)
at java.net.SocketInputStream.read(SocketInputStream.java:171)
at java.net.SocketInputStream.read(SocketInputStream.java:141)
at java.net.SocketInputStream.read(SocketInputStream.java:127)
at redis.clients.util.RedisInputStream.ensureFill(RedisInputStream.java:196)
... 27 more
我查看了 Spring 源代码和 Jedis 源代码——我假设它没有使用 SSL 连接;
JedisConnectionFactory - afterPropertiesSet()--尝试创建集群--在此之下它正在尝试初始化SlotsCache,它使用密码向Redis服务器发出AUTH命令--这是发生“读取超时”的地方;
我了解本地 redis - 您可以进入并运行 auth 命令进行身份验证。但我猜 AWS Redis 可能无法做到这一点,它甚至在运行 AUTH 命令之前就需要有 SSL 连接 - 为什么 Jedis 不使用 SSL 连接?
这是另一个线程"Cannot get Jedis connection" when using SSL with Redis and Spring Data Redis 说,使用 JedisPool 之类的东西 - 但 spring-data-redis 的 JedisConnectionFactory 不接受 JedisPool。有没有其他方法可以做到这一点?
JedisPool jedisPool = new JedisPool("rediss://" + clusterConfigEndPoint + ":6379");
另一个问题 - 其他库使用 redis ssl 连接作为rediss:// - Jedis Client 如何使用 SSL 连接,
任何帮助将不胜感激!
谢谢!
【问题讨论】:
-
更新:我后来发现 Jedis 没有能力支持使用 SSL 连接的集群设置;结果 Spring-Data-Redis 也不支持它。现在,Jedis 和 Spring Data Redis 都支持基于集群的 Redis,带有 SSL。 jira.spring.io/browse/DATAREDIS-974
标签: java amazon-web-services jedis spring-data-redis redis-cluster