使用 ssl 在 AWS 上使用 Spring-boot-starter-data-redis 的启动错误

Posted

技术标签:

【中文标题】使用 ssl 在 AWS 上使用 Spring-boot-starter-data-redis 的启动错误【英文标题】:Startup error using Spring-boot-starter-data-redis on AWS using ssl 【发布时间】:2019-11-24 12:51:40 【问题描述】:

所以,今天遇到了一个有趣的问题,弄乱了 spring-boot-starter-data-rest。我的用例是在 redis 上存储一些具有一定过期时间的数据,以便在该时间过去后立即将其驱逐。我已经配置好了所有东西,并且可以在我的本地 redis 上运行,没有任何问题。尝试使用安全连接 (SSL) 在 AWS 上使用它时会出现问题,并且是一个示例错误:

           at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1578)
           at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:545)
           at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:482)
           at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306)
           at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
           at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302)
           at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
           at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:772)
           at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:839)
           at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:538)
           at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:118)
           at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:766)
           at org.springframework.boot.SpringApplication.createAndRefreshContext(SpringApplication.java:361)
           at org.springframework.boot.SpringApplication.run(SpringApplication.java:307)
           at org.springframework.boot.SpringApplication.run(SpringApplication.java:1191)
           at org.springframework.boot.SpringApplication.run(SpringApplication.java:1180)
           at com.springbootapp.config.Application.main(Application.java:16)
           ... 6 more
   Caused by: org.springframework.dao.InvalidDataAccessApiUsageException: ERR Unsupported CONFIG parameter: notify-keyspace-events; nested exception is redis.clients.jedis.exceptions.JedisDataException: ERR Unsupported CONFIG parameter: notify-keyspace-events
           at org.springframework.data.redis.connection.jedis.JedisExceptionConverter.convert(JedisExceptionConverter.java:44)
           at org.springframework.data.redis.connection.jedis.JedisExceptionConverter.convert(JedisExceptionConverter.java:36)
           at org.springframework.data.redis.PassThroughExceptionTranslationStrategy.translate(PassThroughExceptionTranslationStrategy.java:37)
           at org.springframework.data.redis.FallbackExceptionTranslationStrategy.translate(FallbackExceptionTranslationStrategy.java:37)
           at org.springframework.data.redis.connection.jedis.JedisConnection.convertJedisAccessException(JedisConnection.java:210)
           at org.springframework.data.redis.connection.jedis.JedisConnection.setConfig(JedisConnection.java:633)
           at org.springframework.session.data.redis.config.ConfigureNotifyKeyspaceEventsAction.configure(ConfigureNotifyKeyspaceEventsAction.java:63)
           at org.springframework.session.data.redis.config.annotation.web.http.RedisHttpSessionConfiguration$EnableRedisKeyspaceNotificationsInitializer.afterPropertiesSet(RedisHttpSessionConfiguration.java:167)
           at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1637)
           at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1574)
           ... 22 more
   Caused by: redis.clients.jedis.exceptions.JedisDataException: ERR Unsupported CONFIG parameter: notify-keyspace-events
           at redis.clients.jedis.Protocol.processError(Protocol.java:117)
           at redis.clients.jedis.Protocol.process(Protocol.java:151)
           at redis.clients.jedis.Protocol.read(Protocol.java:205)
           at redis.clients.jedis.Connection.readProtocolWithCheckingBroken(Connection.java:297)
           at redis.clients.jedis.Connection.getStatusCodeReply(Connection.java:196)
           at redis.clients.jedis.Jedis.configSet(Jedis.java:2575)
           at org.springframework.data.redis.connection.jedis.JedisConnection.setConfig(JedisConnection.java:631)
           ... 26 more

我没有使用@EnabledRedisSession,它依赖于我不需要它。

事实证明,大多数示例都是针对此的。

https://***.com/questions/36177688/embedded-redis-cant-start!

我添加了spring redis会话依赖并尝试了

@Bean
public static ConfigureRedisAction configureRedisAction() 
    return ConfigureRedisAction.NO_OP;

@EnableRedisRepositories(enableKeyspaceEvents = EnableKeyspaceEvents.ON_DEMAND)

将其更改为 on_demand 我收到以下错误。

下面显示的我的 redisContainer 失败了。

@EnableAsync
@Configuration
@EnableRedisRepositories(enableKeyspaceEvents = EnableKeyspaceEvents.ON_DEMAND)
public class RedisConfiguration 

    private DeloreanProperties deloreanProperties;

    private ApplicationEventPublisher applicationEventPublisher;

    private RedisConfigProperties redisConfigProperies;

    private Environment environment;

    @Autowired
    public void setDeloreanProperties(DeloreanProperties deloreanProperties) 
        this.deloreanProperties = deloreanProperties;
    

    @Autowired
    public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) 
        this.applicationEventPublisher = applicationEventPublisher;
    

    @Autowired
    public void setEnvironment(Environment environment) 
        this.environment = environment;
    

    @Autowired
    public void setRedisConfigProperies(RedisConfigProperties redisConfigProperies) 
        this.redisConfigProperies = redisConfigProperies;
    

    @Bean
    public JedisConnectionFactory redisConnectionFactory() 
        JedisClientConfigurationBuilder jedisClientConfiguration = JedisClientConfiguration.builder();
        jedisClientConfiguration.connectTimeout(Duration.ofSeconds(60));
        jedisClientConfiguration.usePooling();

        if (Arrays.stream(environment.getActiveProfiles()).anyMatch(env -> (env.equalsIgnoreCase("deployed")))) 
            jedisClientConfiguration.useSsl();
        

        RedisStandaloneConfiguration configuration = new RedisStandaloneConfiguration();
        configuration.setHostName(redisConfigProperies.getHost());
        configuration.setPort(redisConfigProperies.getPort());
        configuration.setPassword(redisConfigProperies.getPassword());
        return new JedisConnectionFactory(configuration, jedisClientConfiguration.build());
    

    @Bean
    public RedisTemplate<?, ?> redisTemplate() 
        RedisTemplate<byte[], byte[]> template = new RedisTemplate<>();
        template.setConnectionFactory(redisConnectionFactory());
        return template;
    

    @Bean
    public RedisMessageListenerContainer redisContainer() 
        RedisMessageListenerContainer container = new RedisMessageListenerContainer();
        container.setConnectionFactory(redisConnectionFactory());
        container.setTaskExecutor(Executors.newFixedThreadPool(deloreanProperties.getListenExecutorFixedThreadPool()));
        return container;
    

    @Bean
    public MessageListener messageListener() 
        KeyExpirationEventMessageListener messageListener = new KeyExpirationEventMessageListener(redisContainer());
        messageListener.setApplicationEventPublisher(applicationEventPublisher);
        return messageListener;
    

【问题讨论】:

【参考方案1】:

感谢 Mota 提出的问题,因为我的团队遇到了同样的问题,您发布的文档非常有用。

在做了一些研究之后,我发现了一个JIRA issue 相关的地方,他们已经在这个Git PR 中解决了这个问题

如您之前所说,问题在于监听器试图获取和修改 Redis 节点的某些参数,而 AWS Elasticache 不允许使用 CONFIG 命令。

在他们的代码中遵循这个comment,您可以通过在@EnableRedisRepositories 中为keyspaceNotificationsConfigParameter 初始化一个空字符串来禁用侦听器运行这些CONFIG 命令 记住还要创建一个新的 Elasticache parameter group,在其中将 notify-keyspace-events 设置为 AKE,并使用新参数组更新您的 Redis 节点

在进行上述更改后,我们没有发现任何问题,并且侦听器正在按预期工作。

【讨论】:

我试过这个。我在启动期间没有收到错误但它没有清理由 spring-data-redis 创建的索引。你知道如何解决这个问题吗?【参考方案2】:

事实证明,对此我们无能为力。这是info block in the documentation。

键空间通知消息侦听器会更改 Redis 中的 notify-keyspace-events 设置(如果尚未设置)。现有设置不会被覆盖,因此您必须正确设置这些设置(或将其留空)。请注意,在 AWS ElastiCache 上禁用了 CONFIG,启用侦听器会导致错误。

【讨论】:

以上是关于使用 ssl 在 AWS 上使用 Spring-boot-starter-data-redis 的启动错误的主要内容,如果未能解决你的问题,请参考以下文章

如何在 AWS EC2 和 ELB 上使用 Godaddy 注册的域实现 SSL 证书

使用 ssl 在 AWS 上使用 Spring-boot-starter-data-redis 的启动错误

在 AWS 中的 Resin 3.1 上使用带有 SSL 的 Google 电子邮件服务

在 AWS EKS 和 Istio Ingress 上使用 GRPC 的 SSL 提供 StatusCode.UNAVAILABLE

尝试从 AWS Lambda 但不是桌面访问 AWS Device Farm 时出现 SSL 证书错误

SSL 不适用于 AWS 上的 Route 53 域