我在带有响应式mongo-driver的scala(akka)中具有较高的CPU使用率吗?

时间:2019-07-01 15:40:47

标签: scala playframework akka cpu-usage reactivemongo

对于我的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)
}

1 个答案:

答案 0 :(得分:4)

我对ReactiveMongo没有任何经验,但是我可以看到您正在为每个请求创建数据库连接。我怀疑每个实例都会在内部分配一个线程池,并且它们最终会堆积起来。您应该只创建DefaultDB的一个实例,并在请求之间重用。

除了对代码的其他注释:

1)无需创建字段globalValuemyResp。尽量避免使用var

2)永远不会抓到Throwable