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