gpt4 book ai didi

java - Lettuce 无法使用 SSL 连接到 Redis 集群,但可以通过将其视为独立节点来使用 SSL 连接到同一 Redis 服务器

转载 作者:行者123 更新时间:2023-12-04 11:30:26 25 4
gpt4 key购买 nike

我有一个 Azure Redis 缓存 - 已启用高级和群集。我一直在尝试使用 spring-boot-starter-data-redis 连接到该 Redis (spring boot 版本:2.3.4.RELEASE,Java 版本:11)并使用 lettuce 客户端,但当我将 Redis 视为 Redis 集群时,Lettuce 抛出以下 SSL 异常,但在将其用作独立 Redis 服务器时连接正常.
我的 pom.xml依赖项是:

<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
Java代码:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.data.redis.RedisProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.*;
import org.springframework.data.redis.connection.lettuce.LettuceClientConfiguration;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.core.StringRedisTemplate;


@Configuration
class LettuceConfig {

@Bean
StringRedisTemplate getStringRedisTemplate(final RedisProperties redisProperties) {
return new StringRedisTemplate(getRedisConnectionFactory(redisProperties));
}

@Bean
RedisConnectionFactory getRedisConnectionFactory(final RedisProperties redisProperties) {

final RedisNode redisNode = RedisNode.newRedisNode()
.listeningAt(redisProperties.getHost(), redisProperties.getPort())
.build();

// Connecting as a Redis Cluster
final RedisClusterConfiguration redisClusterConfiguration = new RedisClusterConfiguration();
redisClusterConfiguration.addClusterNode(redisNode);
redisClusterConfiguration.setPassword(RedisPassword.of(redisProperties.getPassword()));

// Connecting as a Standalone Redis server
final RedisStandaloneConfiguration redisStandaloneConfiguration = new RedisStandaloneConfiguration();
redisStandaloneConfiguration.setHostName(redisProperties.getHost());
redisStandaloneConfiguration.setPort(redisProperties.getPort());
redisStandaloneConfiguration.setPassword(RedisPassword.of(redisProperties.getPassword()));

final LettuceClientConfiguration.LettuceClientConfigurationBuilder lettuceClientConfigurationBuilder =
LettuceClientConfiguration.builder()
.clientName(redisProperties.getClientName())
.commandTimeout(redisProperties.getTimeout());

if (redisProperties.isSsl()) {
lettuceClientConfigurationBuilder.useSsl();
}

final LettuceClientConfiguration lettuceClientConfiguration = lettuceClientConfigurationBuilder.build();

return new LettuceConnectionFactory(redisClusterConfiguration, lettuceClientConfiguration);
}
}

@SpringBootApplication
public class LettuceClusterApplication implements CommandLineRunner {

private final StringRedisTemplate stringRedisTemplate;

@Autowired
public LettuceClusterApplication(final StringRedisTemplate stringRedisTemplate) {
this.stringRedisTemplate = stringRedisTemplate;
}

public static void main(String[] args) {
SpringApplication.run(LettuceClusterApplication.class, args);
}

@Override
public void run(String... args) throws Exception {
System.out.println(stringRedisTemplate.hasKey("abc"));
}
}
使用 redisStandaloneConfiguration 时在 new LettuceConnectionFactory(..., ...) ,代码工作得很好,但如果我使用 redisClusterConfiguration ,代码失败,出现以下异常:
java.lang.IllegalStateException: Failed to execute CommandLineRunner
at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:798) ~[spring-boot-2.3.4.RELEASE.jar:2.3.4.RELEASE]
...
Caused by: org.springframework.data.redis.RedisConnectionFailureException: Redis connection failed; nested exception is io.lettuce.core.RedisConnectionException: Unable to connect to [RedisURI [host='<redacted>.redis.cache.windows.net', port=6380]]
at org.springframework.data.redis.connection.lettuce.LettuceExceptionConverter.convert(LettuceExceptionConverter.java:66) ~[spring-data-redis-2.3.4.RELEASE.jar:2.3.4.RELEASE]
...
Caused by: io.lettuce.core.RedisConnectionException: Unable to connect to [RedisURI [host='<redacted>.redis.cache.windows.net', port=6380]]
at io.lettuce.core.RedisConnectionException.create(RedisConnectionException.java:78) ~[lettuce-core-5.3.4.RELEASE.jar:5.3.4.RELEASE]
...
Caused by: javax.net.ssl.SSLHandshakeException: No subject alternative names matching IP address <redacted> found
...
Caused by: java.security.cert.CertificateException: No subject alternative names matching IP address <redacted> found
at java.base/sun.security.util.HostnameChecker.matchIP(HostnameChecker.java:165) ~[na:na]
...
我的 application.properties文件:
spring.redis.host = <redacted>.redis.cache.windows.net
spring.redis.port = 6380
spring.redis.password = <redacted>
spring.redis.ssl = true
spring.redis.clientName = ${HOSTNAME}
spring.redis.timeout = 100000
更新 : 在 Github 中发现了一个类似的问题: https://github.com/lettuce-io/lettuce-core/issues/246但它说它应该适用于生菜版本> 4.2我的生菜核心版本(捆绑在 spring-boot-starter-data-redis 下)是 5.3.4.RELEASE .
同样值得一试的是说明相同的文档: https://lettuce.io/core/release/reference/#ssl

Lettuce supports SSL connections since version 3.1 on Redis Standalone connections and since version 4.2 on Redis Cluster


也提出了 GitHub 问题: https://github.com/lettuce-io/lettuce-core/issues/1454

最佳答案

如果您的所有节点都具有与主机名相同的 IP 地址(我认为 Azure Cache for Redis 就是这种情况),那么这是您可以将客户端配置为将未解析的 IP 地址映射回主机名的一种方式证书。

    @Bean
ClientResources clientResources(RedisProperties redisProperties) throws UnknownHostException {
var clientResourcesBuilder = DefaultClientResources.builder();
var configuredHost = redisProperties.getHost();
var inetAddresses = Arrays.asList(InetAddress.getAllByName(configuredHost));
MappingSocketAddressResolver resolver = MappingSocketAddressResolver.create(
DnsResolvers.UNRESOLVED,
hostAndPort -> inetAddresses.stream()
.anyMatch(i -> i.getHostAddress().equals(hostAndPort.getHostText())) ?
HostAndPort.of(configuredHost, hostAndPort.getPort()) :
hostAndPort
);
clientResourcesBuilder.socketAddressResolver(resolver);
return clientResourcesBuilder.build();
}
据我所知,这是 Github issue 上列出的解决方案中最可取的。直到微软从头到尾解决问题。

关于java - Lettuce 无法使用 SSL 连接到 Redis 集群,但可以通过将其视为独立节点来使用 SSL 连接到同一 Redis 服务器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64287424/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com