Java 启动后重试与Cassandra节点的连接
我想使用Docker来启动我的应用程序和Cassandra数据库,我想使用Docker Compose来实现这一点。不幸的是,Cassandra的启动速度比我的应用程序慢得多,而且由于我的应用程序急切地初始化Java 启动后重试与Cassandra节点的连接,java,cassandra,Java,Cassandra,我想使用Docker来启动我的应用程序和Cassandra数据库,我想使用Docker Compose来实现这一点。不幸的是,Cassandra的启动速度比我的应用程序慢得多,而且由于我的应用程序急切地初始化集群对象,我得到了以下异常: 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.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驱动程序似乎没有对初始启动应用重试策略。我觉得这有点奇怪。我是否有办法配置驱动程序,使其能够继续尝试连接到服务器,直到成功?尝试增加连接超时,这是AWS等设备上有时会发生的一件事。我认为您正在查看错误日志的后期,在某个时候,它会告诉您由于超时或无法访问网络而无法连接,然后它会将节点标记为不可用 使用phantom,代码如下所示:
val Connector = ContactPoints(Seq(seedHost))
.withClusterBuilder(_.withSocketOptions(
new SocketOptions()
.setReadTimeoutMillis(1500)
.setConnectTimeoutMillis(20000)
)).keySpace("bla")
资源链接:
您应该能够在NoHostAvailableException上编写一些try/catch逻辑,以便在等待5-10秒后重试连接。我建议您在特定时间段之后抛出异常之前只执行几次,您知道异常应该在该时间点开始 示例伪代码
连接makeCassandraConnection(int retryCount){
Exception lastException=新的IllegalStateException();
而(retryCount>0){
试一试{
return doConnectionStuff();
}捕获(无主机可用例外){
lastException=e;
重新计数--;
睡眠(时间单位为秒,toMillis(5));
}
}
抛出最后一个异常;
}
如果您不想更改客户端代码,并且客户端应用程序的docker容器因错误而停止,则可以在docker compose文件中为客户端应用程序使用以下属性
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
无法以这种方式配置Datastax驱动程序 <>如果这只是Docker的一个问题,你不想改变你的代码,你可以考虑使用一个简单的脚本来等待TCP端口在启动你的应用程序之前监听。是卡桑德拉的本地传输端口
其他选项是,但我个人只使用了wait for it,但发现它在docker中使用cassandra时非常有用。如果您协调了许多docker,您应该使用depends-on标记进行docker compose
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
你只有一个Cassandra节点?@SotiriosDelimanolis sure;我不需要更多的本地开发和测试,至少现在是这样。Cassandra还没有开始监听OP示例中的客户机。连接尝试将被拒绝,因为相应端口上没有侦听任何内容。超时不会改变这一点。Dependes-on标记只等待容器启动,Cassandra本身仍需要一些额外的时间来启动。是的,
Dependes-on
实际上不起作用,这是我尝试的第一件事。更重要的是,Dependes-on的条件已在docker 3中删除,所以你不能再等卡桑德拉恢复健康了,看来这就是我要做的。很奇怪,司机并不是自动这样做的。我可能会在他们的bug跟踪器中为这个特性创建一个记录单。如果多个线程试图调用这个方法呢?所有其他线程都必须等待,这是一个性能上的打击,对吗?实际上,我目前正是为了这个目的而使用的。除此之外,它还能够检查TCP端口的可用性。但是,很自然地,我希望驱动程序这样做。是的,这是一个可能的解决方案,但是如果应用程序重启不是免费的(例如,如果它有一些初始化要做),它就不起作用。目前,我的程序不需要进行任何复杂的初始化,但很有可能在将来需要类似的东西。