Как подключить кластер AWS Elasticache Redis к приложению Spring Boot? - PullRequest
5 голосов
/ 11 декабря 2019

У меня есть приложение Spring Boot, которое подключается к кластеру Redis, используя Jedis Connection Factory:

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

и читая список узлов из 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

Теперь мы хотимпереключиться на Elasticache, так как мы все равно размещаем наш кластер Redis на AWS. Это было бы сделано довольно легко. Если AmazonElastiCache lib может быть использован. Затем мы могли бы просто подключиться к кластеру Elasticache с учетными данными AWS, вытащить доступные узлы, поместить его в список и передать его Jedis, а не жестко кодировать их в application.yml, например:

//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;
}

Но команда DevOps сказала, что онине могу настроить доступ AWS во всех лабораториях, и у них есть причины для этого. Также вместо того, чтобы подключаться к AWS и извлекать все доступные кластеры, нам нужно подключиться к определенному по URL.

Поэтому я попытался передать URL-адрес кластера Elasticache непосредственно в Jedis как автономный и как кластер в конфигурации application.yml. В обоих случаях соединение установлено, но когда приложение пытается выполнить запись в Elasticache, оно получает исключение MOVED:

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

Что, как я понимаю, означает, что приложение пыталось выполнить запись в один из узлов в Elasticache, но не 'Невозможно подключиться.

Таким образом, вопрос заключается в том, есть ли способ подключиться к кластеру Elasticache Redis из приложения Spring Boot, используя только URL-адрес кластера Elasticache?

Я знаючто это возможно, если используется Elasticache Memecache. Также драйвер Jedis не является жестким требованием.

Спасибо.

1 Ответ

0 голосов
/ 13 декабря 2019

После некоторых исследований мы узнали, что если конечная точка кластера AWS Elasticache установлена ​​в качестве узла в RedisClusterConfiguration, то драйвер (Jedis или Lettuce) сможет соединиться и найти все узлы в кластере Elasticache. Также, если один из узлов выходит из строя, драйвер может обмениваться данными с кластером Elasticache через какой-то другой узел.

Мы также перешли на драйвер салата при работе над этим обновлением, поскольку салат-латунь является драйвером по умолчанию, предоставляемым в Spring Boot RedisНачал и поддерживает последние версии Redis. Соединения для салата рассчитаны на многопоточность, а джедайс - нет.

Пример кода:

List<String> nodes = Collections.singletonList("****.***.****.****.cache.amazonaws.com:6379");
RedisClusterConfiguration clusterConfiguration = new RedisClusterConfiguration(nodes);
return new LettuceConnectionFactory(clusterConfiguration);
...