web-dev-qa-db-fra.com

Comment connecter le cluster AWS Elasticache Redis à l'application Spring Boot?

J'ai l'application Spring Boot qui se connecte au cluster Redis, à l'aide de Jedis Connection Factory:

RedisClusterConfiguration redisClusterConfiguration = new RedisClusterConfiguration(redisProperties.getCluster().getNodes());
redisClusterConfiguration.setPassword(redisProperties.getPassword());
jedisConnectionFactory = new JedisConnectionFactory(redisClusterConfiguration);

et lecture de la liste des nœuds depuis application.yml:

spring:
  redis:
    Host: 127.0.0.1
    port: 6379
    timeout: 300s
    cluster:
      nodes: 127.0.0.1:6380,127.0.0.1:6381,127.0.0.1:6382

Maintenant, nous voulons passer à Elasticache puisque nous hébergeons notre cluster Redis sur AWS de toute façon. Cela se ferait assez facilement. Si la bibliothèque AmazonElastiCache pouvait être utilisée. Ensuite, nous pourrions simplement nous connecter au cluster Elasticache avec les informations d'identification AWS, extraire les nœuds disponibles, les mettre dans la liste et les transmettre à Jedis au lieu de les coder en dur dans application.yml, comme:

//get cache cluster nodes using AWS api
private List<String> getClusterNodes(){
    AmazonElastiCache client = AmazonElastiCacheClientBuilder.standard().withRegion(Regions.DEFAULT_REGION).build();
    DescribeCacheClustersRequest describeCacheClustersRequest = new DescribeCacheClustersRequest();
    describeCacheClustersRequest.setShowCacheNodeInfo(true);
    List<CacheCluster> cacheClusterList = client.describeCacheClusters(describeCacheClustersRequest).getCacheClusters();
    List<String> nodeList = new ArrayList<>();
    try {
        for (CacheCluster cacheCluster : cacheClusterList) {
            for(CacheNode cacheNode :cacheCluster.getCacheNodes()) {
                String nodeAddr = cacheNode.getEndpoint().getAddress() + ":" +cacheNode.getEndpoint().getPort();
                nodeList.add(nodeAddr);
            }
        }
    }
    catch(Exception e) {
        e.printStackTrace();
    }
    return nodeList;
}

Mais l'équipe DevOps a déclaré qu'elle ne pouvait pas configurer l'accès AWS sur tous les laboratoires et qu'elle avait des raisons à cela. De plus, au lieu de se connecter à AWS et d'extraire tous les clusters disponibles, nous devons nous connecter à un cluster spécifique par URL.

J'ai donc essayé de passer l'URL du cluster Elasticache directement à Jedis en tant que autonome et en tant que cluster dans la configuration application.yml. Dans les deux cas, la connexion est établie, mais lorsque App essaie d'écrire dans Elasticache, son exception MOVED est:

org.springframework.web.util.NestedServletException: Request processing failed; nested exception is org.springframework.data.redis.ClusterRedirectException: Redirect: slot 1209 to 10.10.10.011:6379.; nested exception is redis.clients.jedis.exceptions.JedisMovedDataException: MOVED 1209 10.10.10.102:6379

D'après ce que je comprends, App a tenté d'écrire sur l'un des nœuds d'Elasticache, mais n'a pas pu se connecter.

La question serait donc de savoir s'il existe un moyen de se connecter au cluster Elasticache Redis à partir de l'application Spring Boot en utilisant uniquement l'URL du cluster Elasticache?

Je sais que c'est faisable si Elasticache Memecache est utilisé. Le pilote Jedis n'est pas non plus une exigence difficile.

Je vous remercie.

8
Marius Jaraminas

Inspiré de la réponse ci-dessus:, complétez le code plus détaillé

List<String> nodes = Collections.singletonList("<cluster-Host-name>:<port>");
RedisClusterConfiguration clusterConfiguration = new RedisClusterConfiguration(nodes);

ClusterTopologyRefreshOptions topologyRefreshOptions = ClusterTopologyRefreshOptions.builder().closeStaleConnections(true)
            .enableAllAdaptiveRefreshTriggers().build();

ClusterClientOptions clusterClientOptions = ClusterClientOptions.builder().autoReconnect(true)
            .topologyRefreshOptions(topologyRefreshOptions).validateClusterNodeMembership(false)
            .build();
//If you want to add tuning options
LettuceClientConfiguration  lettuceClientConfiguration = LettuceClientConfiguration.builder().readFrom(ReadFrom.REPLICA_PREFERRED).clientOptions(clusterClientOptions).build();

LettuceConnectionFactory lettuceConnectionFactory = new LettuceConnectionFactory(redisClusterConfiguration, lettuceClientConfiguration);
lettuceConnectionFactory.afterPropertiesSet();//**this is REQUIRED**
StringRedisTemplate redisTemplate = new StringRedisTemplate(lettuceConnectionFactory);
0
Santh