Ошибка запуска с использованием Spring-boot-starter-data-redis на AWS с использованием ssl

Итак, сегодня столкнулся с интересной проблемой, связанной с spring-boot-starter-data-rest. Мой вариант использования — хранить некоторые данные в Redis с некоторым сроком действия, чтобы они были удалены, как только это время истечет. У меня все настроено и работает на моем локальном Redis без каких-либо проблем. Это становится проблемой при попытке работать с ним на AWS с использованием защищенного соединения (SSL) и является примером ошибки:

           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 и это зависит, так как мне это не нужно.

Оказывается, большинство примеров ориентировано на это.

http://www.example.com/!

Я добавил зависимость весеннего сеанса 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;
    }
}

person Mota Nginya    schedule 15.07.2019    source источник


Ответы (2)


Спасибо за вопрос, Мота, так как моя команда столкнулась с той же проблемой, и опубликованная вами документация оказалась очень полезной.

Проведя небольшое исследование, я обнаружил проблему JIRA, связанную с тем, что они уже решили эту проблему. в этом Git PR

Как вы указывали ранее, проблема заключается в том, что слушатель пытается получить и изменить некоторые параметры узла Redis, а AWS Elasticache не разрешает команду CONFIG.

  • После этого comment в своем коде, вы можете запретить прослушивателю выполнение этих команд CONFIG, инициализировав пустую строку для keyspaceNotificationsConfigParameter в вашем @EnableRedisRepositories
  • Не забудьте также создать новую группу параметров Elasticache, где вы устанавливаете notify-keyspace-events в AKE и обновляете свой узел Redis с новой группой параметров

После вышеуказанных изменений мы не видим проблем, и слушатель работает, как задумано.

person justkind    schedule 05.09.2019
comment
Я попробовал это. Я не получаю сообщение об ошибке во время запуска, но он не очищает индексы, созданные spring-data-redis. У вас есть идеи, как это исправить? - person Raashith; 05.09.2020

Оказывается, с этим мало что можно сделать. Вот информационный блок в документации.

Прослушиватель сообщений с уведомлением о пространстве ключей изменяет настройки событий уведомления о пространстве ключей в Redis, если они еще не установлены. Существующие настройки не переопределяются, поэтому вы должны установить эти настройки правильно (или оставить их пустыми). Обратите внимание, что CONFIG отключен в AWS ElastiCache, и включение прослушивателя приводит к ошибке.

person Mota Nginya    schedule 16.07.2019