我目前正致力于将Phantom DSL集成到一个小型Play应用程序中。由于我们计划在Docker环境中运行应用程序,因此我在本地计算机上使用Docker Compose来测试应用程序。
但是,当启动Cassandra实例和Play应用程序时,它无法连接或运行,因为Play应用程序在Cassandra之前可用。
我目前的连接器设置如下:
object Defaults {
val connector = ContactPoint(sys.env("CASSANDRA_URL"), sys.env("CASSANDRA_PORT").toInt)
.withClusterBuilder(_.withSocketOptions(
new SocketOptions().setTcpNoDelay(true))
).keySpace("my_app")
}
将数据库初始化为
class CassandraDB(val keyspace: KeySpaceDef) extends Database(keyspace) {
object users extends ConcreteUsers with keyspace.Connector
object articles extends ConcreteArticles with keyspace.Connector
object comments extends ConcreteComments with keyspace.Connector
}
object CassandraDB extends CassandraDB(Defaults.connector)
我的游戏! controller使用CassandraDB对象
调用数据库def index = Action.async {
CassandraDB.users.getAll.map { users =>
Ok(Json.toJson(users))
}
}
第一次连接到数据库的尝试导致了预期的NoHostAvailableException
com.datastax.driver.core.exceptions.NoHostAvailableException: All host(s) tried for query failed (tried: localhost/127.0.0.1:9042)
之后的任何请求都将引发以下异常:
play.api.UnexpectedException: Unexpected exception[RuntimeException: java.lang.NoClassDefFoundError: Could not initialize class models.CassandraDB$]
一旦发生这种情况,就需要手动重启应用程序才能工作。
在等待Cassandra容器完全初始化时工作正常,这看起来并不理想,我希望在连接失败后重试它
答案 0 :(得分:0)
嗯,我很清楚幻像和/或你的申请没有错吗?当容器正常工作时,两者都能正常工作。
您是否尝试过订购作品?
https://docs.docker.com/compose/startup-order/
修改强>
根据我的答案中的OP问题,可能的解决方案是使用Actor方法,在数据库出局的情况下,您可以使用主管策略。
override def supervisorStrategy: SupervisorStrategy =
OneForOneStrategy(maxNrOfRetries = 5) {
case _: NoHostAvailableException => Restart
case _: Exception => Stop
}
因此,您可以让一个与您的数据库交互的Actor,并且在尝试连接时,如果发生已知错误,您可以在主管上捕获它并决定该怎么做。如果您决定重新启动,则可以使用preRestart方法再次连接。
override def preRestart(reason: Throwable, message: Option[Any]): Unit = {
log.warning(s"Restarting Actor due: {}", reason.getMessage)
//do something here
}
http://doc.akka.io/docs/akka/2.4.11/general/supervision.html http://doc.akka.io/docs/akka/2.4.11/scala/fault-tolerance.html