Exceção em modo de cluster do Lettuce: Ponto de conexão não reconhecido na visão do cluster

O seguinte erro pode ocorrer ao utilizar o cliente Lettuce em um ambiente de cluster Redis:

java.lang.IllegalArgumentException: Connection to 192.168.60.59:7001 not allowed. This connection point is not known in the cluster view

Essa exceção, muitas vezes envolta por um RedisException, indica que o cliente está tentando se conectar a um endereço IP e porta (nó) que não faz parte da visão atual do cluster que ele conhece. O Lettuce mantém um mapa da topologia do cluster, atualizado periodicamente ou sob demanda, e proíbe conexões para nós desconhecidos como uma medida de segurança para evitar redirecionamentos inválidos ou ataques.

A situação costuma surgir quando a topologia do cluster muda (por exemplo, durante uma operação de failover ou adição/remoção de um nó) e a visão do cliente ainda não foi atualizada. O Lettuce carrega a topologia inicial na primeira conexão. Para mitigar esse problema, é recomendável habilitar a atualização adapttaiva da topologia ou, como alternativa menos segura, desabilitar a validação rigorosa dos nós do cluster.

Um exemplo de configuração para Spring Boot que habilita a atualização adaptativa da topologia baseada em certos gatilhos pode ser implementado como mostrado abaixo. Note que a estrutura e os nomes das variáveis foram alterados em relação a exepmlos comuns para ilustrar uma implementação diferente, mas funcional:

import io.lettuce.core.cluster.ClusterTopologyRefreshOptions;
import io.lettuce.core.cluster.ClusterClientOptions;
import io.lettuce.core.ClientOptions;
import org.springframework.boot.autoconfigure.data.redis.LettuceClientConfigurationBuilderCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ConditionalOnClass;
import org.springframework.context.annotation.Configuration;
import java.time.Duration;
import java.util.HashSet;
import java.util.Set;

@Configuration
@ConditionalOnClass(ClusterTopologyRefreshOptions.class)
public class ClusterRefreshConfig {

    @Bean
    @ConditionalOnMissingBean
    public LettuceClientConfigurationBuilderCustomizer redisClusterCustomizer() {
        return builder -> {
            // Define os gatilhos para atualização da topologia
            Set<ClusterTopologyRefreshOptions.RefreshTrigger> triggerSet = new HashSet<>();
            triggerSet.add(ClusterTopologyRefreshOptions.RefreshTrigger.MOVED_REDIRECT);
            triggerSet.add(ClusterTopologyRefreshOptions.RefreshTrigger.ASK_REDIRECT);
            triggerSet.add(ClusterTopologyRefreshOptions.RefreshTrigger.PERSISTENT_RECONNECTS);
            triggerSet.add(ClusterTopologyRefreshOptions.RefreshTrigger.UNKNOWN_NODE);

            // Configura as opções de atualização da topologia
            ClusterTopologyRefreshOptions refreshConfig = ClusterTopologyRefreshOptions.builder()
                    .enableAdaptiveRefreshTrigger(triggerSet)
                    .adaptiveRefreshTriggersTimeout(Duration.ofSeconds(30))
                    .enableAllClusterViews()
                    .build();

            // Constrói as opções avançadas do cliente com a atualização de topologia
            ClientOptions clusterClientOptions = ClusterClientOptions.builder()
                    .topologyRefreshOptions(refreshConfig)
                    .build();

            builder.clientOptions(clusterClientOptions);
        };
    }
}

Esta abordagem faz com que o cliente Lettuce solicite uma atualização da topologia do cluster quando encontrar redirecionamentos MOVED ou ASK, ao tentar se reconectar a um nó de forma persistente, ou ao tentar se comunicar com um nó desconhecido.

Tags: Lettuce Redis java spring-boot cluster

Publicado em 7-13 19:11