Подтвердить что ты не робот

Повторное подключение к Cassandra node при запуске

Я хочу использовать Docker для запуска моего приложения и базы данных Cassandra, и я хотел бы использовать Docker Compose для этого. К сожалению, Cassandra запускается гораздо медленнее, чем мое приложение, и поскольку мое приложение с нетерпением инициализирует объект Cluster, я получаю следующее исключение:

com.datastax.driver.core.exceptions.NoHostAvailableException: All host(s) tried for query failed (tried: cassandra/172.18.0.2:9042 (com.datastax.driver.core.exceptions.TransportException: [cassandra/172.18.0.2:9042] Cannot connect))
    at com.datastax.driver.core.ControlConnection.reconnectInternal(ControlConnection.java:233)
    at com.datastax.driver.core.ControlConnection.connect(ControlConnection.java:79)
    at com.datastax.driver.core.Cluster$Manager.init(Cluster.java:1454)
    at com.datastax.driver.core.Cluster.init(Cluster.java:163)
    at com.datastax.driver.core.Cluster.connectAsync(Cluster.java:334)
    at com.datastax.driver.core.Cluster.connectAsync(Cluster.java:309)
    at com.datastax.driver.core.Cluster.connect(Cluster.java:251)

Согласно stacktrace и небольшой отладке, кажется, что драйвер Java Cassandra не применяет политики повтора к первоначальному запуску. Мне это кажется странным. Есть ли способ настроить драйвер, чтобы он продолжал попытки подключения к серверу до тех пор, пока он не завершится?

4b9b3361

Ответ 1

Вы должны иметь возможность написать логику try/catch в NoHostAvailableException, чтобы повторить соединение после 5-10 секунд ожидания. Я бы рекомендовал сделать это несколько раз, прежде чем бросать исключение через определенный период времени, когда вы знаете, что он должен был начать с этой точки.

Пример псевдокода

Connection makeCassandraConnection(int retryCount) {
    Exception lastException = new IllegalStateException();
    while (retryCount > 0) {
        try {
            return doConnectionStuff();
        } catch (NoHostAvailableException e) {
            lastException = e;
            retryCount--;
            Thread.sleep(TimeUnit.SECONDS.toMillis(5));
        }
    }
    throw lastException;
}

Ответ 2

Если вы не хотите изменять код клиента, а контейнер-докер-клиент клиентского приложения останавливается из-за ошибки, вы можете использовать следующий атрибут для клиентского приложения в файле документации для док-станции.

restart: unless-stopped

Это перезапустит контейнер клиентского приложения столько раз, сколько это произойдет. Пример файла docker-compose.yml:

version: '2'
services:
  cassandra:
    image: cassandra:3.5
    ports:
      - "9042:9042"
      - "9160:9160"
    environment:
      CASSANDRA_CLUSTER_NAME: demo
  app:
    image: your-app
    restart: unless-stopped

Ответ 3

Драйвер Datastax нельзя настроить таким образом.

Если это только проблема с Docker, и вы не хотите менять свой код, вы можете подумать о том, чтобы использовать что-то вроде wait-for-it который представляет собой простой script, который будет ожидать прослушивания TCP-порта перед запуском приложения. 9042 является родным транспортным портом cassandra.

Другие варианты обсуждаются здесь в документации докеров, но я лично использовал только wait-for-it, но нашел, что это полезно при работе с кассандрой внутри докеров.

Ответ 4

Если вы организуете много докеров, вы должны пойти на сборку докеров, в зависимости от тега

version: '2'
services:
  cassandra:
    image: cassandra:3.5
    ports:
      - "9042:9042"
      - "9160:9160"
    environment:
      CASSANDRA_CLUSTER_NAME: demo
  app:
    image: your-app
    restart: unless-stopped
    depends_on:
      - cassandra

Ответ 5

Попробуйте увеличить тайм-аут соединения, это одна вещь иногда происходит на AWS и тому подобное. Я думаю, что вы смотрите на поздний этап в журнале ошибок, в какой-то момент он должен сказать вам, что он не может подключиться из-за тайм-аута или недоступной сети, а затем он помещает узлы как недоступные.

Используя phantom, код выглядит следующим образом:

val Connector = ContactPoints(Seq(seedHost))
    .withClusterBuilder(_.withSocketOptions(
      new SocketOptions()
      .setReadTimeoutMillis(1500)
      .setConnectTimeoutMillis(20000)
    )).keySpace("bla")

Ссылка на ресурс:

com.datastax.driver.core.exceptions.NoHostAvailableException # 445