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

2022-09-01 16:16:23

我想使用 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和一些调试,似乎Cassandra Java驱动程序不会将重试策略应用于初始启动。这对我来说似乎有点奇怪。有没有办法配置驱动程序,以便它将继续尝试连接到服务器,直到成功为止?


答案 1

您应该能够在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;
}

答案 2

如果不想更改客户端代码,并且客户端应用程序的 Docker 容器由于错误而停止,则可以在 docker 组合文件中对客户端应用使用以下属性。

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

推荐