对于我的Scala应用程序,即使负载很小,我的CPU使用率也很高,平均负载也很高(397)。当我尝试分析线程转储时,我看到总数为1471,其中732个等待,700个timed_waiting和39个可运行。我看到了reactmongo-akka.actor 697线程和reactmonmon-scheduler 687线程。将反应式mongo驱动程序升级到“ org.reactivemongo”%“ play2-reactivemongo_2.11”%“ 0.12.6-play25”之后,我看到了这个问题。我正在使用Akka默认调度程序。
我运行了该命令sar -u来检查到底是什么导致了cpu的升高,并发现了上下文切换(每秒267319个),但是我没有看到任何I / O操作导致此问题。
这是我的数据库连接设置
def isMongoUp: JsValue = {
var returnValue: JsValue = null
var myresp: ObjectNode = null
val connectedFuture: Future[JsValue] = getDatabase.map { list =>
list match {
case sth: DefaultDB =>
try {
returnValue = statusCheck("", sth)
myresp = returnValue.as[ObjectNode]
myresp.put("status", true)
returnValue = Json.toJson(myresp)
} finally {
sth.connection.close()
}
case _ =>
myresp = new ObjectNode(JsonNodeFactory.instance)
myresp.put("status", false)
returnValue = Json.toJson(myresp)
}
returnValue
}.recover {
case error: Throwable =>
error.printStackTrace()
myresp = new ObjectNode(JsonNodeFactory.instance)
myresp.put("status", false)
returnValue = Json.toJson(myresp)
returnValue
}
val timeout = scala.concurrent.duration.Duration(10, "seconds")
returnValue = Await.result(connectedFuture, timeout)
returnValue
}
def getDatabase: Future[DefaultDB] =
{
val driver = new MongoDriver
val mongoUri = configuration.getString("mongodb.uri").get;
val uri = MongoConnection.parseURI(mongoUri).get;
val con = driver.connection(uri)
val dn = uri.db.get
val db = con.database(dn)
db
}
def statusCheck(dbConn: String = "db", db: DefaultDB): JsValue =
Await.result({
val commandDoc = BSONDocument("serverStatus" -> 1)
val runner = Command.run(BSONSerializationPack)
val futureResult = runner.apply(db, runner.rawCommand(commandDoc)).one[BSONDocument]
futureResult.map {
doc => reactivemongo.play.json.BSONFormats.toJSON(doc.bson)
}
}, Duration.Inf)
}
答案 0 :(得分:4)
我对ReactiveMongo没有任何经验,但是我可以看到您正在为每个请求创建数据库连接。我怀疑每个实例都会在内部分配一个线程池,并且它们最终会堆积起来。您应该只创建DefaultDB
的一个实例,并在请求之间重用。
除了对代码的其他注释:
1)无需创建字段globalValue
和myResp
。尽量避免使用var
。
2)永远不会抓到Throwable