在 Phantom DSL 和 Play 中自动重试不可用主机 (NoHostAvailableException)! 2个
Automatic Retry on unavailable hosts (NoHostAvailableException) in Phantom DSL and Play! 2
我目前正致力于将 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)
还有我的游戏!控制器使用 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 容器完全初始化工作正常,但这似乎并不理想,我希望在连接失败后重试
好吧,我很清楚幻影 and/or 您的应用程序没有错,对吗?当容器正常工作时,两者都可以正常工作。
你试过订购你的撰写吗?
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
我目前正致力于将 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)
还有我的游戏!控制器使用 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 容器完全初始化工作正常,但这似乎并不理想,我希望在连接失败后重试
好吧,我很清楚幻影 and/or 您的应用程序没有错,对吗?当容器正常工作时,两者都可以正常工作。
你试过订购你的撰写吗?
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