У меня высокая загрузка процессора в scala (akka) с реактивным монго-драйвером? - PullRequest
0 голосов
/ 01 июля 2019

В моем приложении scala у меня высокая загрузка ЦП и средняя загрузка (397), даже при небольшой нагрузке. Когда я пытался проанализировать threaddump, я вижу общее количество 1471, в которых 732 ожидания, 700 timed_waiting & 39 runnable,Я вижу потоки 693 реактивного монго и реактив 687 и реактивный планировщик реактивного монета. Я вижу эту проблему после обновления драйвера реактивного монго до "org.reactivemongo"% "play2 -activetivemongo_2.11"% "0.12.6-play25".Я использую диспетчер по умолчанию akka.

Я запустил эту команду sar -u, чтобы проверить, что именно является причиной высокой загрузки процессора, и обнаружил переключение контекста (267319 в секунду), и я не вижу никаких операций ввода-вывода.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 Ответ

4 голосов
/ 01 июля 2019

У меня нет опыта работы с ReactiveMongo, но я вижу, что вы создаете соединение с базой данных при каждом запросе.Я подозреваю, что каждый экземпляр выделяет пул потоков внутри, и они в конечном итоге накапливаются.Вы должны создать только один экземпляр DefaultDB и повторно использовать его между запросами.

Кроме того, пара дополнительных комментариев к коду:

1) Нет необходимости создавать поля globalValue и myResp.Старайтесь избегать var с в целом.

2) Никогда не поймайте Throwable

...