无法将 SpringBoot 连接到 docker 上的 redis-cluster
Can not connect SpringBoot to redis-cluster on docker
我想在 docker 上创建本地 redis 集群。
- 我尝试在本地 docker.
上创建 redis-cluster
- 我有 3 个 docker。
- docker redis:5.0.1-高山 172.18.1.1
- docker redis:5.0.1-高山 172.18.1.2
- docker redis:5.0.1-高山 172.18.1.3
- 它们通过 mynet 网络连接。
- 我做了redis集群
docker 172.18.1.1 $> redis-cli --cluster create --cluster-replicas 0 172.18.1.1:6379 172.18.1.2:6379 172.18.1.3:6379
它们很好用!!
$> redis-cli -c
127.0.0.1:6379> set hello redis
OK
127.0.0.1:6379> get hello
"redis"
127.0.0.1:6379>
问题是无法从 Spring 引导应用程序连接到 redis-cluster。
- Spring引导版本:1.5.7.RELEASE
- REDIS LIB 版本:redis.clients:jedis:2.9.0
- 这里有一些代码
spring.redis.cluster.nodes=127.0.0.1:36379,127.0.0.1:36380,127.0.0.1:36381
spring.redis.cluster.max-redirects=6
@Component
@ConfigurationProperties(prefix = "spring.redis.cluster")
public class RedisClusterConfigurationProperties {
List<String> nodes;
public List<String> getNodes() {
return nodes;
}
public void setNodes(List<String> nodes) {
this.nodes = nodes;
}
}
@Configuration
@Service
public class SomesService {
@Autowired
private RedisClusterConfigurationProperties clusterProperties;
@Bean
public JedisPoolConfig jedisPoolConfig() {
final JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
return jedisPoolConfig;
}
@Bean(name = "redisTemplate")
public RedisTemplate redisTemplate() {
RedisTemplate redisTemplate = new RedisTemplate();
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setValueSerializer(new StringRedisSerializer());
redisTemplate.setConnectionFactory(connectionFactory());
redisTemplate.setExposeConnection(true);
return redisTemplate;
}
private RedisConnectionFactory connectionFactory() {
final RedisClusterConfiguration clusterConfig = new RedisClusterConfiguration(clusterProperties.getNodes());
final JedisConnectionFactory jedisConnectionFactory = new JedisConnectionFactory(
clusterConfig, jedisPoolConfig());
jedisConnectionFactory.setUsePool(true);
return jedisConnectionFactory;
}
}
结果
org.springframework.data.redis.ClusterStateFailureException: Could not retrieve cluster information. CLUSTER NODES returned with error.
- 172.18.1.1:6379 failed: Could not get a resource from the pool
- 172.18.1.2:6379 failed: Could not get a resource from the pool
- 172.18.1.3:6379 failed: Could not get a resource from the pool
at org.springframework.data.redis.connection.jedis.JedisClusterConnection$JedisClusterTopologyProvider.getTopology(JedisClusterConnection.java:4237)
at org.springframework.data.redis.connection.ClusterCommandExecutor.getClusterTopology(ClusterCommandExecutor.java:349)
at org.springframework.data.redis.connection.ClusterCommandExecutor.executeCommandOnAllNodes(ClusterCommandExecutor.java:188)
at org.springframework.data.redis.connection.jedis.JedisClusterConnection.info(JedisClusterConnection.java:3128)
--- removed my package sorry ;-)
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:738)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157)
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:136)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:673)
--- removed my package sorry ;-)
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.junit.runners.model.FrameworkMethod.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:75)
at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27)
at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:86)
at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:84)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:252)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94)
at org.junit.runners.ParentRunner.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access[=15=]0(ParentRunner.java:58)
at org.junit.runners.ParentRunner.evaluate(ParentRunner.java:268)
at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
2019-07-23 15:48:01.579 INFO 13741 --- [ Thread-5] o.s.w.c.s.GenericWebApplicationContext : Closing org.springframework.web.context.support.GenericWebApplicationContext@305ffe9e: startup date [Tue Jul 23 15:47:42 KST 2019]; root of context hierarchy
2019:07:23 15:48:01.579 INFO --- [Thread-5] o.s.w.c.s.GenericWebApplicationContext : - 984 Closing org.springframework.web.context.support.GenericWebApplicationContext@305ffe9e: startup date [Tue Jul 23 15:47:42 KST 2019]; root of context hierarchy
Process finished with exit code 255
- 错误信息
无法检索集群信息。集群节点返回错误。
- 172.18.1.1:6379 失败:Could not get a resource from the pool
* '172.18.1.1' 是 docker 主机 IP。
* '127.0.0.1:36379' 是我在 application.properties 文件中输入的值。
正在 docker
- 但是!!!如果我将 war Spring 引导构建的结果放入通过 mynet 连接的 docker 中,它就可以工作了!
- 构建项目 > 将 war 复制到另一个 docker > 运行 中的 war。它的工作!很好。
- 我认为 redis-cluster 不允许代理传递或其他...
- 有谁知道如何在本地制作本地redis集群docker?
问题在于,在 Redis 集群中,客户端从 Redis 节点本身获取所有 Redis 节点的 URL。
因此,在您的情况下,Spring 引导应用程序向配置的节点之一发送 "cluster nodes" 请求 (127.0.0.1:36379,127.0.0.1:36380,127.0.0.1:36381) .
作为响应,它接收所有 Redis 节点的 URL,在您的情况下是 172.18.1.1:6379 172.18.1.2:6379 172.18.1.3:6379 并尝试与它们通信。
由于这是内部 Docker 网络,您会收到连接失败错误。
您想要的是将每个 Redis 节点配置为具有不同的 "advertised" 主机和端口。
这样,客户端将收到他们可以访问的 URL,而不是内部主机和端口。
这是您应该添加的配置参数:
cluster-announce-ip: The IP address to announce.
cluster-announce-port: The data port to announce.
cluster-announce-bus-port: The cluster bus port to announce.
请参阅此博客 post,其中对此进行了更详细的解释:https://get-reddie.com/blog/redis4-cluster-docker-compose/
我想在 docker 上创建本地 redis 集群。
- 我尝试在本地 docker. 上创建 redis-cluster
- 我有 3 个 docker。
- docker redis:5.0.1-高山 172.18.1.1
- docker redis:5.0.1-高山 172.18.1.2
- docker redis:5.0.1-高山 172.18.1.3
- 它们通过 mynet 网络连接。
- 我做了redis集群
docker 172.18.1.1 $> redis-cli --cluster create --cluster-replicas 0 172.18.1.1:6379 172.18.1.2:6379 172.18.1.3:6379
它们很好用!!
$> redis-cli -c
127.0.0.1:6379> set hello redis
OK
127.0.0.1:6379> get hello
"redis"
127.0.0.1:6379>
问题是无法从 Spring 引导应用程序连接到 redis-cluster。
- Spring引导版本:1.5.7.RELEASE
- REDIS LIB 版本:redis.clients:jedis:2.9.0
- 这里有一些代码
spring.redis.cluster.nodes=127.0.0.1:36379,127.0.0.1:36380,127.0.0.1:36381
spring.redis.cluster.max-redirects=6
@Component
@ConfigurationProperties(prefix = "spring.redis.cluster")
public class RedisClusterConfigurationProperties {
List<String> nodes;
public List<String> getNodes() {
return nodes;
}
public void setNodes(List<String> nodes) {
this.nodes = nodes;
}
}
@Configuration
@Service
public class SomesService {
@Autowired
private RedisClusterConfigurationProperties clusterProperties;
@Bean
public JedisPoolConfig jedisPoolConfig() {
final JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
return jedisPoolConfig;
}
@Bean(name = "redisTemplate")
public RedisTemplate redisTemplate() {
RedisTemplate redisTemplate = new RedisTemplate();
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setValueSerializer(new StringRedisSerializer());
redisTemplate.setConnectionFactory(connectionFactory());
redisTemplate.setExposeConnection(true);
return redisTemplate;
}
private RedisConnectionFactory connectionFactory() {
final RedisClusterConfiguration clusterConfig = new RedisClusterConfiguration(clusterProperties.getNodes());
final JedisConnectionFactory jedisConnectionFactory = new JedisConnectionFactory(
clusterConfig, jedisPoolConfig());
jedisConnectionFactory.setUsePool(true);
return jedisConnectionFactory;
}
}
结果
org.springframework.data.redis.ClusterStateFailureException: Could not retrieve cluster information. CLUSTER NODES returned with error.
- 172.18.1.1:6379 failed: Could not get a resource from the pool
- 172.18.1.2:6379 failed: Could not get a resource from the pool
- 172.18.1.3:6379 failed: Could not get a resource from the pool
at org.springframework.data.redis.connection.jedis.JedisClusterConnection$JedisClusterTopologyProvider.getTopology(JedisClusterConnection.java:4237)
at org.springframework.data.redis.connection.ClusterCommandExecutor.getClusterTopology(ClusterCommandExecutor.java:349)
at org.springframework.data.redis.connection.ClusterCommandExecutor.executeCommandOnAllNodes(ClusterCommandExecutor.java:188)
at org.springframework.data.redis.connection.jedis.JedisClusterConnection.info(JedisClusterConnection.java:3128)
--- removed my package sorry ;-)
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:738)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157)
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:136)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:673)
--- removed my package sorry ;-)
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.junit.runners.model.FrameworkMethod.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:75)
at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27)
at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:86)
at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:84)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:252)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94)
at org.junit.runners.ParentRunner.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access[=15=]0(ParentRunner.java:58)
at org.junit.runners.ParentRunner.evaluate(ParentRunner.java:268)
at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
2019-07-23 15:48:01.579 INFO 13741 --- [ Thread-5] o.s.w.c.s.GenericWebApplicationContext : Closing org.springframework.web.context.support.GenericWebApplicationContext@305ffe9e: startup date [Tue Jul 23 15:47:42 KST 2019]; root of context hierarchy
2019:07:23 15:48:01.579 INFO --- [Thread-5] o.s.w.c.s.GenericWebApplicationContext : - 984 Closing org.springframework.web.context.support.GenericWebApplicationContext@305ffe9e: startup date [Tue Jul 23 15:47:42 KST 2019]; root of context hierarchy
Process finished with exit code 255
- 错误信息
无法检索集群信息。集群节点返回错误。
- 172.18.1.1:6379 失败:Could not get a resource from the pool
* '172.18.1.1' 是 docker 主机 IP。
* '127.0.0.1:36379' 是我在 application.properties 文件中输入的值。
正在 docker
- 但是!!!如果我将 war Spring 引导构建的结果放入通过 mynet 连接的 docker 中,它就可以工作了!
- 构建项目 > 将 war 复制到另一个 docker > 运行 中的 war。它的工作!很好。
- 我认为 redis-cluster 不允许代理传递或其他...
- 有谁知道如何在本地制作本地redis集群docker?
问题在于,在 Redis 集群中,客户端从 Redis 节点本身获取所有 Redis 节点的 URL。
因此,在您的情况下,Spring 引导应用程序向配置的节点之一发送 "cluster nodes" 请求 (127.0.0.1:36379,127.0.0.1:36380,127.0.0.1:36381) .
作为响应,它接收所有 Redis 节点的 URL,在您的情况下是 172.18.1.1:6379 172.18.1.2:6379 172.18.1.3:6379 并尝试与它们通信。 由于这是内部 Docker 网络,您会收到连接失败错误。
您想要的是将每个 Redis 节点配置为具有不同的 "advertised" 主机和端口。 这样,客户端将收到他们可以访问的 URL,而不是内部主机和端口。
这是您应该添加的配置参数:
cluster-announce-ip: The IP address to announce.
cluster-announce-port: The data port to announce.
cluster-announce-bus-port: The cluster bus port to announce.
请参阅此博客 post,其中对此进行了更详细的解释:https://get-reddie.com/blog/redis4-cluster-docker-compose/