お知らせ
2023.12.5(Tue)
目次
こんにちは、堀部です。
Spring Session + Redis(AWS ElastiCache)でセッション管理を行う方法 の過程で発生したエラーの解決方法です。
今回はクラスタ構成で冗長化されている環境で、Redisへの接続を行った時のエラーです。ノードを指定して接続を行っていましたが、どうもうまく接続ができませんでした。
org.springframework.data.redis.RedisConnectionFailureException: No reachable node in cluster; nested exception is redis.clients.jedis.exceptions.JedisNoReachableClusterNodeException: No reachable node in cluster at org.springframework.data.redis.connection.jedis.JedisExceptionConverter.convert(JedisExceptionConverter.java:67) ~[spring-data-redis-1.8.13.RELEASE.jar:na] at org.springframework.data.redis.connection.jedis.JedisExceptionConverter.convert(JedisExceptionConverter.java:41) ~[spring-data-redis-1.8.13.RELEASE.jar:na] at org.springframework.data.redis.PassThroughExceptionTranslationStrategy.translate(PassThroughExceptionTranslationStrategy.java:37) ~[spring-data-redis-1.8.13.RELEASE.jar:na] at org.springframework.data.redis.FallbackExceptionTranslationStrategy.translate(FallbackExceptionTranslationStrategy.java:37) ~[spring-data-redis-1.8.13.RELEASE.jar:na] at org.springframework.data.redis.connection.jedis.JedisClusterConnection.convertJedisAccessException(JedisClusterConnection.java:3985) ~[spring-data-redis-1.8.13.RELEASE.jar:na] at org.springframework.data.redis.connection.jedis.JedisClusterConnection.sMembers(JedisClusterConnection.java:1512) ~[spring-data-redis-1.8.13.RELEASE.jar:na] at org.springframework.data.redis.core.DefaultSetOperations$7.doInRedis(DefaultSetOperations.java:129) ~[spring-data-redis-1.8.13.RELEASE.jar:na] at org.springframework.data.redis.core.DefaultSetOperations$7.doInRedis(DefaultSetOperations.java:126) ~[spring-data-redis-1.8.13.RELEASE.jar:na] at org.springframework.data.redis.core.RedisTemplate.execute(RedisTemplate.java:207) ~[spring-data-redis-1.8.13.RELEASE.jar:na] at org.springframework.data.redis.core.RedisTemplate.execute(RedisTemplate.java:169) ~[spring-data-redis-1.8.13.RELEASE.jar:na] at org.springframework.data.redis.core.AbstractOperations.execute(AbstractOperations.java:91) ~[spring-data-redis-1.8.13.RELEASE.jar:na] at org.springframework.data.redis.core.DefaultSetOperations.members(DefaultSetOperations.java:126) ~[spring-data-redis-1.8.13.RELEASE.jar:na] at org.springframework.data.redis.core.DefaultBoundSetOperations.members(DefaultBoundSetOperations.java:91) ~[spring-data-redis-1.8.13.RELEASE.jar:na] at org.springframework.session.data.redis.RedisSessionExpirationPolicy.cleanExpiredSessions(RedisSessionExpirationPolicy.java:131) ~[spring-session-1.3.2.RELEASE.jar:na] at org.springframework.session.data.redis.RedisOperationsSessionRepository.cleanupExpiredSessions(RedisOperationsSessionRepository.java:398) ~[spring-session-1.3.2.RELEASE.jar:na] at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_171] at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_171] at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_171] at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_171] at org.springframework.scheduling.support.ScheduledMethodRunnable.run(ScheduledMethodRunnable.java:65) ~[spring-context-4.2.1.RELEASE.jar:4.2.1.RELEASE] at org.springframework.scheduling.support.DelegatingErrorHandlingRunnable.run(DelegatingErrorHandlingRunnable.java:54) ~[spring-context-4.2.1.RELEASE.jar:4.2.1.RELEASE] at org.springframework.scheduling.concurrent.ReschedulingRunnable.run(ReschedulingRunnable.java:81) [spring-context-4.2.1.RELEASE.jar:4.2.1.RELEASE] at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) [na:1.8.0_171] at java.util.concurrent.FutureTask.run(FutureTask.java:266) [na:1.8.0_171] at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:180) [na:1.8.0_171] at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293) [na:1.8.0_171] at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [na:1.8.0_171] at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [na:1.8.0_171] at java.lang.Thread.run(Thread.java:748) [na:1.8.0_171] Caused by: redis.clients.jedis.exceptions.JedisNoReachableClusterNodeException: No reachable node in cluster at redis.clients.jedis.JedisSlotBasedConnectionHandler.getConnection(JedisSlotBasedConnectionHandler.java:57) ~[jedis-2.9.0.jar:na] at redis.clients.jedis.JedisSlotBasedConnectionHandler.getConnectionFromSlot(JedisSlotBasedConnectionHandler.java:74) ~[jedis-2.9.0.jar:na] at redis.clients.jedis.JedisClusterCommand.runWithRetries(JedisClusterCommand.java:116) ~[jedis-2.9.0.jar:na] at redis.clients.jedis.JedisClusterCommand.runBinary(JedisClusterCommand.java:60) ~[jedis-2.9.0.jar:na] at redis.clients.jedis.BinaryJedisCluster.smembers(BinaryJedisCluster.java:588) ~[jedis-2.9.0.jar:na] at org.springframework.data.redis.connection.jedis.JedisClusterConnection.sMembers(JedisClusterConnection.java:1510) ~[spring-data-redis-1.8.13.RELEASE.jar:na] ... 23 common frames omitted ERROR TaskUtils$LoggingErrorHandler - Unexpected error occurred in scheduled task. org.springframework.data.redis.RedisConnectionFailureException: No reachable node in cluster; nested exception is redis.clients.jedis.exceptions.JedisNoReachableClusterNodeException: No reachable node in cluster at org.springframework.data.redis.connection.jedis.JedisExceptionConverter.convert(JedisExceptionConverter.java:67) ~[spring-data-redis-1.8.13.RELEASE.jar:na] at org.springframework.data.redis.connection.jedis.JedisExceptionConverter.convert(JedisExceptionConverter.java:41) ~[spring-data-redis-1.8.13.RELEASE.jar:na] at org.springframework.data.redis.PassThroughExceptionTranslationStrategy.translate(PassThroughExceptionTranslationStrategy.java:37) ~[spring-data-redis-1.8.13.RELEASE.jar:na] at org.springframework.data.redis.FallbackExceptionTranslationStrategy.translate(FallbackExceptionTranslationStrategy.java:37) ~[spring-data-redis-1.8.13.RELEASE.jar:na] at org.springframework.data.redis.connection.jedis.JedisClusterConnection.convertJedisAccessException(JedisClusterConnection.java:3985) ~[spring-data-redis-1.8.13.RELEASE.jar:na] at org.springframework.data.redis.connection.jedis.JedisClusterConnection.sMembers(JedisClusterConnection.java:1512) ~[spring-data-redis-1.8.13.RELEASE.jar:na] at org.springframework.data.redis.core.DefaultSetOperations$7.doInRedis(DefaultSetOperations.java:129) ~[spring-data-redis-1.8.13.RELEASE.jar:na] at org.springframework.data.redis.core.DefaultSetOperations$7.doInRedis(DefaultSetOperations.java:126) ~[spring-data-redis-1.8.13.RELEASE.jar:na] at org.springframework.data.redis.core.RedisTemplate.execute(RedisTemplate.java:207) ~[spring-data-redis-1.8.13.RELEASE.jar:na] at org.springframework.data.redis.core.RedisTemplate.execute(RedisTemplate.java:169) ~[spring-data-redis-1.8.13.RELEASE.jar:na] at org.springframework.data.redis.core.AbstractOperations.execute(AbstractOperations.java:91) ~[spring-data-redis-1.8.13.RELEASE.jar:na] at org.springframework.data.redis.core.DefaultSetOperations.members(DefaultSetOperations.java:126) ~[spring-data-redis-1.8.13.RELEASE.jar:na] at org.springframework.data.redis.core.DefaultBoundSetOperations.members(DefaultBoundSetOperations.java:91) ~[spring-data-redis-1.8.13.RELEASE.jar:na] at org.springframework.session.data.redis.RedisSessionExpirationPolicy.cleanExpiredSessions(RedisSessionExpirationPolicy.java:131) ~[spring-session-1.3.2.RELEASE.jar:na] at org.springframework.session.data.redis.RedisOperationsSessionRepository.cleanupExpiredSessions(RedisOperationsSessionRepository.java:398) ~[spring-session-1.3.2.RELEASE.jar:na] at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_171] at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_171] at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_171] at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_171] at org.springframework.scheduling.support.ScheduledMethodRunnable.run(ScheduledMethodRunnable.java:65) ~[spring-context-4.2.1.RELEASE.jar:4.2.1.RELEASE] at org.springframework.scheduling.support.DelegatingErrorHandlingRunnable.run(DelegatingErrorHandlingRunnable.java:54) ~[spring-context-4.2.1.RELEASE.jar:4.2.1.RELEASE] at org.springframework.scheduling.concurrent.ReschedulingRunnable.run(ReschedulingRunnable.java:81) [spring-context-4.2.1.RELEASE.jar:4.2.1.RELEASE] at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) [na:1.8.0_171] at java.util.concurrent.FutureTask.run(FutureTask.java:266) [na:1.8.0_171] at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:180) [na:1.8.0_171] at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293) [na:1.8.0_171] at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [na:1.8.0_171] at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [na:1.8.0_171] at java.lang.Thread.run(Thread.java:748) [na:1.8.0_171] Caused by: redis.clients.jedis.exceptions.JedisNoReachableClusterNodeException: No reachable node in cluster at redis.clients.jedis.JedisSlotBasedConnectionHandler.getConnection(JedisSlotBasedConnectionHandler.java:57) ~[jedis-2.9.0.jar:na] at redis.clients.jedis.JedisSlotBasedConnectionHandler.getConnectionFromSlot(JedisSlotBasedConnectionHandler.java:74) ~[jedis-2.9.0.jar:na] at redis.clients.jedis.JedisClusterCommand.runWithRetries(JedisClusterCommand.java:116) ~[jedis-2.9.0.jar:na] at redis.clients.jedis.JedisClusterCommand.runBinary(JedisClusterCommand.java:60) ~[jedis-2.9.0.jar:na] at redis.clients.jedis.BinaryJedisCluster.smembers(BinaryJedisCluster.java:588) ~[jedis-2.9.0.jar:na] at org.springframework.data.redis.connection.jedis.JedisClusterConnection.sMembers(JedisClusterConnection.java:1510) ~[spring-data-redis-1.8.13.RELEASE.jar:na] ... 23 common frames omitted
エラー発生時のバージョンは以下になります。
いろいろと調べた結果、SpringSession / Jedis はクラスターモードかつSSL有効化には対応していないようで、RedisClusterではSSLで接続できないことがわかりました。
今後、SSL接続ができるようになるかもしれませんが、少なくとも私がRedisを使った開発を行っていた2018年8月頃はSSL接続はサポートされていませんでした。非SSLだと接続できるため、対応としてはSSLでの接続をやめました。
そのほかの接続方法にRedisSentinelを使った方法があるようですが、こちらは検証していないのでもしかしたらできるかもしれません。
<!-- Redis接続情報 --> <bean id="redisClusterConfiguration" class="org.springframework.data.redis.connection.RedisClusterConfiguration"> <property name="clusterNodes"> <set> <bean class="org.springframework.data.redis.connection.RedisNode"> <constructor-arg name="host" value="ノード1のホスト名" /> <constructor-arg name="port" value="6379" type="int" /> </bean> <bean class="org.springframework.data.redis.connection.RedisNode"> <constructor-arg name="host" value="ノード2のホスト名" /> <constructor-arg name="port" value="6379" type="int" /> </bean> </set> </property> <property name="maxRedirects" value="5" /> </bean> <bean id="jedisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory" p:host-name="localhost" p:port="6379" p:useSsl="false"> <constructor-arg ref="redisClusterConfiguration" /> </bean>