启动时重试与Cassandra节点的连接

时间:2016-08-02 14:55:59

标签: java cassandra

我想使用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)

根据堆栈跟踪和一些调试,似乎Cassandra Java驱动程序不会将重试策略应用于初始启动。这对我来说似乎有点奇怪。有没有办法让我配置驱动程序,以便它继续尝试连接到服务器,直到成功为止?

5 个答案:

答案 0 :(得分:12)

您应该能够在NoHostAvailableException上编写一些try / catch逻辑,以便在等待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;
}

答案 1 :(得分:2)

如果您不想更改客户端代码,并且客户端应用程序的docker容器由于错误而停止,则可以在docker-compose文件中为客户端应用程序使用以下属性。< / p>

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

答案 2 :(得分:1)

无法以这种方式配置Datastax驱动程序。

如果这只是Docker的一个问题而您不想更改代码,可以考虑使用wait-for-it之类的东西,这是一个简单的脚本,等待TCP端口在开始之前监听你的申请。 9042是cassandra的本地传输端口。

其他选项是discussed here in the docker documentation,但我个人只使用了wait-for-it,但发现它在docker中使用cassandra时非常有用。

答案 3 :(得分:0)

如果你编排了许多码头工人,那么你应该选择一个基于标签的码头构图

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

答案 4 :(得分:-2)

尝试增加连接超时,这有时会发生在AWS等上。我认为您正在查看错误日志的后期阶段,在某些时候它应该告诉您由于超时或无法访问的网络而无法连接,然后它将节点标记为不可用。

使用幻像,代码如下:

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

资源链接:

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