Какой эффект имеет использование Action.async, так как Play использует Netty, который не блокирует

Поскольку Netty является неблокирующим сервером, какой эффект приводит к изменению действия на использование .async?

def index = Action { ... }

против

def index = Action.async { ... }

Я понимаю, что с помощью .async вы получите Future[SimpleResult]. Но так как Netty не блокирует, Play все равно будет делать что-то подобное под прикрытием?

Как это повлияет на пропускную способность /масштабируемость? Это сложный вопрос, чтобы ответить, где это зависит от других факторов?

Причина, по которой я спрашиваю, в том, что у меня есть свой собственный Action, и я хотел сбросить тайм-аут для каждого файла запрос страницы, поэтому я делаю это async вызов:

object MyAction extends ActionBuilder[abc123] {
  def invokeBlock[A](request: Request[A], block: (abc123[A]) => Future[SimpleResult]) = {
    ...
    val result: Future[SimpleResult] = block(new abc123(..., result))
    result.map(_.withCookies(...))
  }
}

Отрывок из приведенного выше фрагмента в том, что я использую Future[SimpleResult], это похоже на вызов Action.async но это внутри самого моего действия?

Я хочу понять, как это повлияет на дизайн моего приложения. Похоже, что только из-за возможности устанавливать файлы cookie для каждого отдельного запроса я перешел с блокировки на неблокирование. Но я сбит с толку, так как Netty не блокирует, может быть, я ничего не изменил в реальности, поскольку это было уже асинхронно?

Или я просто создал еще один асинхронный вызов, встроенный в другой?

Надеясь, что кто-то может уточнить это с некоторыми деталями, и как или как это повлияет на производительность /пропускную способность.

12 голосов | спросил Blankman 11 J0000006Europe/Moscow 2014, 18:54:31

2 ответа


0

def index = Action { ... } неблокирует, вы правы.

Цель Action.async состоит в упрощении работы с Futures в ваших действиях.

Например:

def index = Action.async {
  val allOptionsFuture: Future[List[UserOption]] = optionService.findAll()
  allOptionFuture map {
    options =>
      Ok(views.html.main(options))
  }
}

Здесь мой сервис возвращает Future, и чтобы избежать извлечения результата, я просто сопоставляю его с Future[SimpleResult] и Action.async позаботятся обо всем остальном.

Если бы мой сервис возвращал List[UserOption] напрямую, я мог бы просто использовать Action.apply, но под капотом все равно будет неблокирующим.

Если вы посмотрите на исходный код Action, вы даже увидите, что apply в конечном итоге вызывает async: https://github.com/playframework/playframework/blob/2.3.x/framework/src/play/src/main/scala/play/api/mvc/Action.scala#L432

ответил vptheron 11 J0000006Europe/Moscow 2014, 19:04:07
0

Я случайно наткнулся на этот вопрос, мне нравится ответ от @vptheron, и я также хочу поделиться тем, что я прочитал из книги " Реактивные веб-приложения ", которая, я думаю, также отличный.

  

Разработчик Action.async ожидает получить функцию типа Request => Future[Result]. Действия, объявленные таким образом, не сильно отличаются от простых вызовов Action { request => ... }, единственное отличие состоит в том, что Play знает, что Action.async уже асинхронны, поэтому они не переносят их содержимое в будущий блок.

     

Правильно. По умолчанию Play будет планировать асинхронное выполнение любого тела действия с пулом веб-рабочих по умолчанию, перенося выполнение в будущем. Единственная разница между Action и Action.async что во втором случае мы заботимся о предоставлении асинхронных вычислений.

Он также представил один образец:

def listFiles = Action { implicit request =>
  val files = new java.io.File(".").listFiles
  Ok(files.map(_.getName).mkString(", "))
}

, что проблематично, учитывая использование блокирующего API java.io.File.

  

Здесь API java.io.File выполняет блокирующую операцию ввода-вывода, а это означает, что один из немногих потоков в пуле веб-работников Play будет взломан, пока ОС выяснит список файлов в каталоге выполнения. Эту ситуацию вам следует избегать любой ценой, поскольку это означает, что в рабочем пуле могут не хватить потоков.

-

  

Инструмент реактивного аудита, доступный по адресу https://github.com/octo-online/реактивный аудит направлен на блокировку вызовов в проекте.

Надеюсь, это тоже поможет.

ответил Scott YAN 7 Jpm1000000pmSun, 07 Jan 2018 14:42:01 +030018 2018, 14:42:01

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132