Исключение, пойманное в RequestBodyHandler

#scala #amazon-s3 #netty #nio

#скала #amazon-s3 #нетти #нио

Вопрос:

ниже приведен код, когда пользователь загружает видео из мобильного приложения в S3

 def uploadVideo = Action(parse.multipartFormData) { implicit request =>
      try {
        var height = 0
        var width = 0
        request.body.files.map { mov =>
          var videoName = System.currentTimeMillis()   ".mpeg"
          amazonS3Client.putObject(bucketVideos, videoName, mov.ref.file)
        }
        val map = Map("result" -> "success")
        Ok(write(map))
      } catch {
        case e: Exception =>
          Ok(write(Map("result" -> "error")))
      }
  }
 

приведенный выше код работает нормально, но в случае отмены пользователем загрузки видео возникает ошибка

     [error] play - Exception caught in RequestBodyHandler
java.nio.channels.ClosedChannelException: null
    at org.jboss.netty.channel.socket.nio.AbstractNioWorker.cleanUpWriteBuffer(AbstractNioWorker.java:434) ~[netty.jar:na]
    at org.jboss.netty.channel.socket.nio.AbstractNioWorker.writeFromUserCode(AbstractNioWorker.java:129) ~[netty.jar:na]
    at org.jboss.netty.channel.socket.nio.NioServerSocketPipelineSink.handleAcceptedSocket(NioServerSocketPipelineSink.java:99) ~[netty.jar:na]
    at org.jboss.netty.channel.socket.nio.NioServerSocketPipelineSink.eventSunk(NioServerSocketPipelineSink.java:36) ~[netty.jar:na]
    at org.jboss.netty.channel.Channels.write(Channels.java:725) ~[netty.jar:na]
    at org.jboss.netty.handler.codec.oneone.OneToOneEncoder.doEncode(OneToOneEncoder.java:71) ~[netty.jar:na]
 

и это не идет на то, чтобы поймать блока!!

1. может ли это нанести вред серверу или нет?(потому что в случае возникновения ошибки не требуется никакого ответа)

2. если да, как обработать?

Ответ №1:

Все это происходит во внутренних компонентах Play, которые обрабатывают синтаксический анализ тела Request . Фактически, во время загрузки на ваш сервер вы еще даже не достигли try блока, потому что загрузка файла не завершена. Только после завершения загрузки у вас есть TemporaryFile доступное.

Так что нет, вы не можете поймать эту ошибку, да и зачем вам это нужно? Пользователь закрыл соединение. Они даже не ждут ответа, так зачем же его посылать? Пусть Игра справится с этим.

Однако это также не очень хороший способ обработки загрузки. Для небольших файлов это приемлемо, но если кто-то проксирует огромную загрузку видео через ваш сервер на S3, это приведет к:

  1. Для обработки ответа потребуется почти в два раза больше времени (что приведет к зависанию пользователя во время загрузки на S3).
  2. Заблокируйте один из потоков Play для обработки запросов на все время, пока файл загружается в S3, и, учитывая достаточное количество таких загрузок (совсем немного), вы больше не сможете обрабатывать запросы до завершения загрузки.

Подумайте, по крайней мере, о создании отдельного ExecutionContext для использования для обработки загрузок, или, что еще лучше, рассмотрите возможность загрузки пользователя непосредственно в S3 через подписанную форму, что вообще избавило бы от необходимости прокси-загрузки.

Комментарии:

1. я отправляю аналогичный вопрос для проверки, пожалуйста, просмотрите его codereview.stackexchange.com/questions/55544 /…