【发布时间】:2019-12-27 07:12:07
【问题描述】:
我正在尝试通过使用 spring-boot-starter-data-redis 和 lettuce 库以集群模式连接到 Redis 并获得以下异常,
2019-08-21 00:55:42.695 WARN 75 --- [ioEventLoop-6-1] i.l.c.c.topology.ClusterTopologyRefresh : Unable to connect to myhostname.service:6379
java.util.concurrent.CompletionException: java.net.UnknownHostException: myhostname.service: Name or service not known
at java.util.concurrent.CompletableFuture.encodeThrowable(CompletableFuture.java:292) ~[na:1.8.0_181]
at java.util.concurrent.CompletableFuture.completeThrowable(CompletableFuture.java:308) ~[na:1.8.0_181]
at java.util.concurrent.CompletableFuture.uniApply(CompletableFuture.java:593) ~[na:1.8.0_181]
at java.util.concurrent.CompletableFuture$UniApply.tryFire(CompletableFuture.java:577) ~[na:1.8.0_181]
at java.util.concurrent.CompletableFuture.postComplete(CompletableFuture.java:474) ~[na:1.8.0_181]
at java.util.concurrent.CompletableFuture.completeExceptionally(CompletableFuture.java:1977) ~[na:1.8.0_181]
at io.lettuce.core.AbstractRedisClient.lambda$initializeChannelAsync$1(AbstractRedisClient.java:275) ~[lettuce-core-5.0.4.RELEASE.jar!/:na]
at io.netty.util.concurrent.DefaultPromise.notifyListener0(DefaultPromise.java:511) ~[netty-common-4.1.25.Final.jar!/:4.1.25.Final]
at io.netty.util.concurrent.DefaultPromise.notifyListenersNow(DefaultPromise.java:485) ~[netty-common-4.1.25.Final.jar!/:4.1.25.Final]
at io.netty.util.concurrent.DefaultPromise.notifyListeners(DefaultPromise.java:424) ~[netty-common-4.1.25.Final.jar!/:4.1.25.Final]
at io.netty.util.concurrent.DefaultPromise.setFailure(DefaultPromise.java:112) ~[netty-common-4.1.25.Final.jar!/:4.1.25.Final]
at io.netty.channel.DefaultChannelPromise.setFailure(DefaultChannelPromise.java:89) ~[netty-transport-4.1.25.Final.jar!/:4.1.25.Final]
at io.netty.bootstrap.Bootstrap.doResolveAndConnect0(Bootstrap.java:216) ~[netty-transport-4.1.25.Final.jar!/:4.1.25.Final]
at io.netty.bootstrap.Bootstrap.access$000(Bootstrap.java:49) ~[netty-transport-4.1.25.Final.jar!/:4.1.25.Final]
at io.netty.bootstrap.Bootstrap$1.operationComplete(Bootstrap.java:188) ~[netty-transport-4.1.25.Final.jar!/:4.1.25.Final]
at io.netty.bootstrap.Bootstrap$1.operationComplete(Bootstrap.java:174) ~[netty-transport-4.1.25.Final.jar!/:4.1.25.Final]
at io.netty.util.concurrent.DefaultPromise.notifyListener0(DefaultPromise.java:511) ~[netty-common-4.1.25.Final.jar!/:4.1.25.Final]
at io.netty.util.concurrent.DefaultPromise.notifyListenersNow(DefaultPromise.java:485) ~[netty-common-4.1.25.Final.jar!/:4.1.25.Final]
at io.netty.util.concurrent.DefaultPromise.notifyListeners(DefaultPromise.java:424) ~[netty-common-4.1.25.Final.jar!/:4.1.25.Final]
at io.netty.util.concurrent.DefaultPromise.trySuccess(DefaultPromise.java:103) ~[netty-common-4.1.25.Final.jar!/:4.1.25.Final]
at io.netty.channel.DefaultChannelPromise.trySuccess(DefaultChannelPromise.java:84) ~[netty-transport-4.1.25.Final.jar!/:4.1.25.Final]
at io.netty.channel.AbstractChannel$AbstractUnsafe.safeSetSuccess(AbstractChannel.java:978) ~[netty-transport-4.1.25.Final.jar!/:4.1.25.Final]
at io.netty.channel.AbstractChannel$AbstractUnsafe.register0(AbstractChannel.java:512) ~[netty-transport-4.1.25.Final.jar!/:4.1.25.Final]
at io.netty.channel.AbstractChannel$AbstractUnsafe.access$200(AbstractChannel.java:423) ~[netty-transport-4.1.25.Final.jar!/:4.1.25.Final]
at io.netty.channel.AbstractChannel$AbstractUnsafe$1.run(AbstractChannel.java:482) ~[netty-transport-4.1.25.Final.jar!/:4.1.25.Final]
at io.netty.util.concurrent.AbstractEventExecutor.safeExecute(AbstractEventExecutor.java:163) ~[netty-common-4.1.25.Final.jar!/:4.1.25.Final]
at io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:404) ~[netty-common-4.1.25.Final.jar!/:4.1.25.Final]
at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:465) ~[netty-transport-4.1.25.Final.jar!/:4.1.25.Final]
at io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:884) ~[netty-common-4.1.25.Final.jar!/:4.1.25.Final]
at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30) ~[netty-common-4.1.25.Final.jar!/:4.1.25.Final]
at java.lang.Thread.run(Thread.java:748) ~[na:1.8.0_181]
Caused by: java.net.UnknownHostException: master1.event-store-service-V-70125f6-2-1566348843-redis.service: Name or service not known
at java.net.Inet4AddressImpl.lookupAllHostAddr(Native Method) ~[na:1.8.0_181]
at java.net.InetAddress$2.lookupAllHostAddr(InetAddress.java:928) ~[na:1.8.0_181]
at java.net.InetAddress.getAddressesFromNameService(InetAddress.java:1323) ~[na:1.8.0_181]
at java.net.InetAddress.getAllByName0(InetAddress.java:1276) ~[na:1.8.0_181]
at java.net.InetAddress.getAllByName(InetAddress.java:1192) ~[na:1.8.0_181]
at java.net.InetAddress.getAllByName(InetAddress.java:1126) ~[na:1.8.0_181]
at java.net.InetAddress.getByName(InetAddress.java:1076) ~[na:1.8.0_181]
at io.netty.util.internal.SocketUtils$8.run(SocketUtils.java:146) ~[netty-common-4.1.25.Final.jar!/:4.1.25.Final]
at io.netty.util.internal.SocketUtils$8.run(SocketUtils.java:143) ~[netty-common-4.1.25.Final.jar!/:4.1.25.Final]
at java.security.AccessController.doPrivileged(Native Method) ~[na:1.8.0_181]
at io.netty.util.internal.SocketUtils.addressByName(SocketUtils.java:143) ~[netty-common-4.1.25.Final.jar!/:4.1.25.Final]
at io.netty.resolver.DefaultNameResolver.doResolve(DefaultNameResolver.java:43) ~[netty-resolver-4.1.25.Final.jar!/:4.1.25.Final]
at io.netty.resolver.SimpleNameResolver.resolve(SimpleNameResolver.java:63) ~[netty-resolver-4.1.25.Final.jar!/:4.1.25.Final]
at io.netty.resolver.SimpleNameResolver.resolve(SimpleNameResolver.java:55) ~[netty-resolver-4.1.25.Final.jar!/:4.1.25.Final]
at io.netty.resolver.InetSocketAddressResolver.doResolve(InetSocketAddressResolver.java:57) ~[netty-resolver-4.1.25.Final.jar!/:4.1.25.Final]
at io.netty.resolver.InetSocketAddressResolver.doResolve(InetSocketAddressResolver.java:32) ~[netty-resolver-4.1.25.Final.jar!/:4.1.25.Final]
at io.netty.resolver.AbstractAddressResolver.resolve(AbstractAddressResolver.java:108) ~[netty-resolver-4.1.25.Final.jar!/:4.1.25.Final]
at io.netty.bootstrap.Bootstrap.doResolveAndConnect0(Bootstrap.java:208) ~[netty-transport-4.1.25.Final.jar!/:4.1.25.Final]
... 18 common frames omitted
注意:“myhostname.service”是由于我使用了 consul,我可以 ping myhostname.service 也可以使用“redis-cli -c -h myhostname.service -p 6379”命令连接到它。
我连接redis的代码是,
@Configuration
@ConfigurationProperties(prefix = "redis")
public class LettuceCacheConfig {
private static Logger logger = LoggerFactory.getLogger(LettuceCacheConfig.class);
private static Long topologyRefreshDuration = 10L;
private static int maxRedirects = 3;
private String servers;
private String profileName;
private String password;
private PoolConfig poolConfig = new PoolConfig();
class PoolConfig {
int maxTotal;
int maxIdle;
int minIdle;
public PoolConfig() {
}
}
public LettuceClientConfiguration getLettuceClientConfig() {
final ClusterTopologyRefreshOptions options = ClusterTopologyRefreshOptions.builder()
.enablePeriodicRefresh(Duration.of(topologyRefreshDuration, ChronoUnit.MINUTES))
.enableAllAdaptiveRefreshTriggers().dynamicRefreshSources(true).build();
final LettuceClientConfiguration lettuceClientConfig = LettuceClientConfiguration.builder()
.clientOptions(ClusterClientOptions.builder().topologyRefreshOptions(options)
.validateClusterNodeMembership(false).build())
.build();
return lettuceClientConfig;
}
private GenericObjectPoolConfig getPoolingConfiguration() {
final GenericObjectPoolConfig config = new GenericObjectPoolConfig();
config.setMaxIdle(this.poolConfig.getMaxIdle());
config.setMaxTotal(this.poolConfig.getMaxTotal());
config.setMinIdle(this.poolConfig.getMinIdle());
return config;
}
public RedisClusterConfiguration getClusterConfiguration() {
final RedisClusterConfiguration clusterConfiguration = new RedisClusterConfiguration();//new RedisClusterConfiguration(getRedisServers());
String hostPort = getRedisServers().get(0);
String tokens[] = hostPort.split(":");
logger.info("REDIS HOST IS {}", tokens[0]);
logger.info("REDIS PORT IS {}", tokens[1]);
clusterConfiguration.clusterNode(tokens[0], Integer.parseInt(tokens[1]));
clusterConfiguration.setMaxRedirects(maxRedirects);
logger.info("PASSWORD is {}",password);
clusterConfiguration.setPassword(RedisPassword.of(password));
return clusterConfiguration;
}
private List<String> getRedisServers() {
String tokens[] = servers.split(",");
logger.debug("Redis Servers are {}", Arrays.toString(tokens));
return Arrays.asList(tokens);
}
@Bean
public RedisConnectionFactory getLettuceConnectionFactory() {
return new LettuceConnectionFactory(getClusterConfiguration(),
getLettuceClientConfig());
}
}
因为我在 java.net.InetAddress.getByName("hostname") 遇到异常,所以我尝试过,
从我的应用容器运行 redis-cli 以连接到 redis 集群容器成功。(如上所述。)
由于我在 java.net.InetAddress.getByName("hostname") 处遇到异常,我使用我的 redis 主机名从我的应用程序容器内部尝试了相同的方法。成功了,没有抛出 UnknownHostException。
从应用容器 ping 到 redis 主机有效。
我确实在本地机器上设置了 redis-cluster,它在上面的代码中运行良好,唯一的变化是我提供了 127.0.0.1:6379 而不是 hostname.service:6379。
我正在使用 spring-boot-starter-parent:2.0.3.RELEASE 和 lettuce-core:5.0.4。代码有问题吗?
【问题讨论】:
-
看起来您正在本地机器上部署 hostname.service,然后,编辑您的 /etc/hosts 名称 (linux) 或 C:\Windows\System32\Drivers\etc\hosts (windows)
-
@VinhNT 在本地机器上运行良好,没有领事和容器。该问题发生在容器化 Redis 和应用程序中,但是当我使用 docker exec -it
sh 登录到应用程序容器时,我可以使用相同的服务名称连接到 redis 容器或集群,在刷新拓扑期间我得到 UnknownHost 异常。 -
当你从机器A向hostname.service发出请求时,机器A需要知道hostname.service在哪里。如果您要将服务部署到 docker,那么您的 docker 可以被视为机器 A。您的 docker 需要知道 hostname.service 在哪里,您需要以某种方式编辑该 docker 的主机文件或将其更改为 ip地址
-
@VinhNT 对不起,我没听明白。 docker 容器(应用程序和 redis 容器)都在 consul 中注册为“服务”,因此它们能够使用各自的服务名称相互 ping 通。假设应用程序容器的服务名称是 abc.service,redis 容器的服务名称是 master1.redis.service,那么两者都能够相互 ping 通。但奇怪的是生菜给出了这个例外。 Consul 充当容器的查找器,这似乎工作正常,因为我说过我正在使用 redis-cli 从应用程序容器连接到 redis 容器。
-
将主机名添加到设置文件:etc/host
标签: java spring-boot redis spring-data-redis lettuce