Ошибка подключения приложения Java Spring к кластеру ScyllaDB в Docker

У меня есть кластер ScyllaDB, успешно работающий на докере, но у меня возникают проблемы с подключением при попытке подключить к нему приложение Spring Boot.

Кластер кажется здоровым:

Datacenter: DC1
===============
Status=Up/Down
|/ State=Normal/Leaving/Joining/Moving
--  Address     Load       Tokens       Owns    Host ID                               Rack
UN  172.19.0.3  205.31 KB  256          ?       c387bd38-cf37-4c70-a8a3-db586f6410c4  Rack1
UN  172.19.0.2  101.61 KB  256          ?       89dda41e-70c5-43a5-a4a7-ce126007a1e1  Rack1
UN  172.19.0.4  210.34 KB  256          ?       58dfe868-a7ac-47a5-b3e9-dae610ef0bc9  Rack1

CONTAINER ID   IMAGE                   COMMAND                  CREATED         STATUS         PORTS                                                            NAMES
b90d0357abee   scylladb/scylla:4.5.0   "/docker-entrypoint.…"   2 minutes ago   Up 2 minutes   22/tcp, 7000-7001/tcp, 9042/tcp, 9160/tcp, 9180/tcp, 10000/tcp   scylla-node2
19f19cb2e631   scylladb/scylla:4.5.0   "/docker-entrypoint.…"   2 minutes ago   Up 2 minutes   22/tcp, 7000-7001/tcp, 9042/tcp, 9160/tcp, 9180/tcp, 10000/tcp   scylla-node3
c98b0b1aa018   scylladb/scylla:4.5.0   "/docker-entrypoint.…"   2 minutes ago   Up 2 minutes   22/tcp, 7000-7001/tcp, 9042/tcp, 9160/tcp, 9180/tcp, 10000/tcp   scylla-node1

И CQL работает без проблем:

docker exec -it scylla-node1 cqlsh
Connected to  at 172.19.0.2:9042.
[cqlsh 5.0.1 | Cassandra 3.0.8 | CQL spec 3.3.1 | Native protocol v4]
Use HELP for help.
cqlsh>

Я пытаюсь подключить свое Java-приложение к кластеру с помощью драйверов датастакс (версия Scylla-Driver-core 3.11.2.0):

Cluster cluster = Cluster.builder().addContactPoints("172.19.0.3", "172.19.0.2", "172.19.0.4")
                .build();
System.out.println("Connected to cluster " + cluster.getMetadata().getClusterName());

но я получаю следующее исключение:

2022-05-08 18:00:02.928  INFO 4760 --- [  restartedMain] com.datastax.driver.core.NettyUtil       : Did not find Netty's native epoll transport in the classpath, defaulting to NIO.
2022-05-08 18:00:09.149  WARN 4760 --- [r1-nio-worker-0] com.datastax.driver.core.Connection      : Error creating netty channel to /172.19.0.4:9042

io.netty.channel.ConnectTimeoutException: connection timed out: /172.19.0.4:9042
    at io.netty.channel.nio.AbstractNioChannel$AbstractNioUnsafe$1.run(AbstractNioChannel.java:261) ~[netty-transport-4.1.75.Final.jar:4.1.75.Final]
    at io.netty.util.concurrent.PromiseTask.runTask(PromiseTask.java:98) [netty-common-4.1.75.Final.jar:4.1.75.Final]
    at io.netty.util.concurrent.ScheduledFutureTask.run(ScheduledFutureTask.java:170) [netty-common-4.1.75.Final.jar:4.1.75.Final]
    at io.netty.util.concurrent.AbstractEventExecutor.safeExecute$$$capture(AbstractEventExecutor.java:164) [netty-common-4.1.75.Final.jar:4.1.75.Final]
    at io.netty.util.concurrent.AbstractEventExecutor.safeExecute(AbstractEventExecutor.java) [netty-common-4.1.75.Final.jar:4.1.75.Final]
    at io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:469) [netty-common-4.1.75.Final.jar:4.1.75.Final]
    at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:503) [netty-transport-4.1.75.Final.jar:4.1.75.Final]
    at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:986) [netty-common-4.1.75.Final.jar:4.1.75.Final]
    at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74) [netty-common-4.1.75.Final.jar:4.1.75.Final]
    at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30) [netty-common-4.1.75.Final.jar:4.1.75.Final]

Exception in thread "restartedMain" java.lang.reflect.InvocationTargetException
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:49)
Caused by: com.datastax.driver.core.exceptions.NoHostAvailableException: All host(s) tried for query failed (tried: /172.19.0.4:9042 (com.datastax.driver.core.exceptions.TransportException: [/172.19.0.4:9042] Cannot connect), /172.19.0.3:9042 (com.datastax.driver.core.exceptions.TransportException: [/172.19.0.3:9042] Cannot connect), /172.19.0.2:9042 (com.datastax.driver.core.exceptions.TransportException: [/172.19.0.2:9042] Cannot connect))
    at com.datastax.driver.core.ControlConnection.reconnectInternal(ControlConnection.java:270)
    at com.datastax.driver.core.ControlConnection.connect(ControlConnection.java:109)
    at com.datastax.driver.core.Cluster$Manager.negotiateProtocolVersionAndConnect(Cluster.java:1921)
    at com.datastax.driver.core.Cluster$Manager.init(Cluster.java:1832)
    at com.datastax.driver.core.Cluster.getMetadata(Cluster.java:476)
    at com.dt.package.ScyllaConnection.connect_and_query(ScyllaConnection.java:15)
    at com.dt.package.MyApp.main(MyApp.java:12)
    ... 5 more

Пример файла docker-compose:

  scylla-node2:
    container_name: scylla-node2
    image: scylladb/scylla:4.5.0
    restart: always
    command: --seeds=scylla-node1,scylla-node2 --smp 1 --memory 750M --overprovisioned 1 --api-address 0.0.0.0
    volumes:
      - "./scylla/scylla.yaml:/etc/scylla/scylla.yaml"
      - "./scylla/cassandra-rackdc.properties.dc1:/etc/scylla/cassandra-rackdc.properties"
    networks:
      web:

Этот же код работает при попытке подключения к кластеру Scylla Cloud (с правильными IP-адресами). Я пропустил что-то простое здесь?

Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Версия Java на основе версии загрузки
Версия Java на основе версии загрузки
Если вы зайдете на официальный сайт Spring Boot , там представлен start.spring.io , который упрощает создание проектов Spring Boot, как показано ниже.
Документирование API с помощью Swagger на Springboot
Документирование API с помощью Swagger на Springboot
В предыдущей статье мы уже узнали, как создать Rest API с помощью Springboot и MySql .
1
0
36
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Проблема может быть вызвана тем, что вы пытаетесь подключиться к узлам ScyllaDB с их внутренними IP-адресами докера.

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

Используя docker compose, вы можете экспортировать порт контейнера, используя поле ports. Например:

  scylla-node2:
    container_name: scylla-node2
    image: scylladb/scylla:4.5.0
    restart: always
    command: --seeds=scylla-node1,scylla-node2 --smp 1 --memory 750M --overprovisioned 1 --api-address 0.0.0.0
    ports:
      - 9043:9042
    volumes:
      - "./scylla/scylla.yaml:/etc/scylla/scylla.yaml"
      - "./scylla/cassandra-rackdc.properties.dc1:/etc/scylla/cassandra-rackdc.properties"
    networks:
      web:

В этом примере мы предоставляем порт контейнера 9042 порту хоста 9043.

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

  scylla-node1:
    ...
    ports:
      - 9042:9042
    ...
  scylla-node2:
    ...
    ports:
      - 9043:9042
    ...
  scylla-node3:
    ...
    ports:
      - 9044:9042
    ...

Разные узлы будут использовать один и тот же хост, на котором работают контейнеры докеров. Чтобы подключиться к ним из вашего приложения Spring, вам нужно что-то вроде следующего:

Cluster cluster =
  Cluster.builder()
    .addContactPointsWithPorts(
      new InetSocketAddress("127.0.0.1", 9042),
      new InetSocketAddress("127.0.0.1", 9043),
      new InetSocketAddress("127.0.0.1", 9044)
    );

System.out.println("Connected to cluster " + cluster.getMetadata().getClusterName());

Обратите внимание на использование в коде метода addContactPointsWithPorts вместо addContactPoints.

Спасибо за подробное объяснение jccampanero! Кажется, мне еще есть чему поучиться в отношении докера. Я изменил код, как вы объяснили, и теперь соединение с кластером работает нормально.

Gustavo Correa 09.05.2022 00:59

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

jccampanero 10.05.2022 23:24

Другие вопросы по теме