当前位置: 首页 > 知识库问答 >
问题:

莴苣不能使用SSL连接到Redis群集,但可以将其视为独立节点,使用SSL连接到同一个Redis服务器

劳华灿
2023-03-14

我启用了用于Redis的Azure缓存-高级和集群。我一直在尝试使用spring-boot-starter-data-redis(Spring booversion:2.3.4. RELEASE,Javaversion:11)并使用lettuce客户端连接到该Redis,但当我将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"));
    }
}

new LettuceConnectionFactory(...,...)中使用redisStandard aloneConfiguration时,代码工作正常,但如果我使用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]
    ...

我的应用程序。属性文件:

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但它说它应该适用于莴苣版本

从Redis独立连接的3.1版和Redis集群的4.2版开始,Lettuce支持SSL连接

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


共有2个答案

钱睿范
2023-03-14

与独立模式下的连接不同,在集群模式下连接到Azure redis是一个两步过程

  1. 连接到<代码>

你得到没有主题替代名称匹配IP地址的原因

在大多数客户端库中,您可以通过配置或覆盖SSL证书验证来绕过此问题,以根据特定redis缓存的主机名验证服务器证书。

E、 g.in.Net StackExchange。redis有一个名为“sslhost”的配置设置可用于此目的。

希望莴苣也有同样的效果。

邵骁
2023-03-14

如果所有节点的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问题上列出的解决方案中最可取的,直到微软最终解决了问题。

 类似资料:
  • 问题内容: 我正在满足以下要求的应用程序(Spring): 从Redis Server1读取数据 从Redis Server2读取数据 从Redis Server3读取数据 和 将信息保存到MySQL。 有人可以给我们一个思路,使用Spring Data Redis连接到不同的Redis服务器。 获得了链接:http : //forum.spring.io/forum/spring- projec

  • 当我试图按照以下部署指南连接到主节点时,我面临着MasternotFounderRorr:https://docs.bitnami.com/tutorials/deploy-redis-sentinel-production-cluster/ 连接主Redis Sentinel节点的代码是: 我面对红魔。哨兵。MasternotFounderRorr:没有为“MyMaster”错误找到master

  • 问题内容: 我是Redis的新手…我最近刚拿起Redisent来在PHP中使用Redis …并且我玩得很开心!但是,我注册了Redis服务,并一直在努力使用该服务… URI字符串如下: redis:// [用户名]:[pass] @ [服务器] .redistogo.com:[端口] / Redisent客户端只需输入主机名和端口…并且我没有地方输入用户名/密码…:-/我也一直在摆弄fsockop

  • 我使用spring boot data redis连接到redis群集,使用版本2.1.3,配置如下: 但是,在操作过程中,始终会收到警告异常消息,如下所示: 这似乎是莴苣的问题,如何映射远程主机

  • 我在从Lambda函数连接Elasticache时遇到问题,我已完成以下操作: 创建了一个新的安全组 Internet正常工作,我通过打开URL验证stackoverflow.com。但是Elasticache自动发现超时。是否需要进行任何额外的配置? 更新I将安全组的入站规则添加到端口6379,现在仍然超时。

  • 这就是第一台服务器的样子: 这是第二台服务器的样子: 第一台服务器运行良好,但当我试图运行第二台服务器时,我会得到follwing错误,这意味着到第一台服务器的连接失败。如果有人能帮助我,我会很高兴的!