twirl play framework scala playframework

scala - twirl - playframework forms



Play Framework: Subidas de archivos: ¿bloqueo o no bloqueo? (1)

¿Cómo se manejarán 100 solicitudes simultáneas de carga lenta (cantidad de subprocesos)?

Depende. La cantidad de hilos reales que se utilizan no es realmente relevante. De forma predeterminada, Play utiliza una cantidad de subprocesos igual a la cantidad de núcleos de CPU disponibles. Pero esto no significa que si tienes 4 núcleos, estás limitado a 4 procesos concurrentes a la vez. Las solicitudes HTTP en Play se procesan de forma asincrónica en un ExecutionContext interno especial provisto por Akka. Los procesos que se ejecutan en un ExecutionContext pueden compartir subprocesos, siempre que no sean bloqueantes, lo que Akka elimina. Todo esto se puede configurar de diferentes maneras. Consulte Descripción de Play Thread Pools .

El Iteratee que consume los datos del cliente debe hacer algunos bloqueos para escribir los fragmentos del archivo en el disco, pero hecho en trozos pequeños (y rápidos), esto no debería causar que otras cargas de archivos se bloqueen.

Lo que más me preocuparía es la cantidad de E / S de disco que su servidor puede manejar. 100 subidas lentas pueden estar bien, pero no se puede decir sin una evaluación comparativa. En algún momento, tendrá problemas cuando la entrada del cliente exceda la velocidad que su servidor puede escribir en el disco. Esto tampoco funcionará en un entorno distribuido. Casi siempre elijo omitir el servidor Play por completo y subir cargas directas a Amazon S3.

¿Se cargará el archivo almacenado en la memoria o transmitido directamente al disco?

Todos los archivos temporales se transmiten al disco. Bajo el capó, todos los datos enviados desde el cliente al servidor se leen usando la biblioteca iteratee de forma asíncrona. Para cargas múltiples, no es diferente. Los datos del cliente son consumidos por un Iteratee , que transmite los fragmentos del archivo a un archivo temporal en el disco. Por lo tanto, al usar el parse.temporaryFile BodyParser , request.body es solo un identificador de un archivo temporal en el disco, y no el archivo almacenado en la memoria.

Vale la pena señalar que aunque Play puede manejar esas solicitudes de una manera no bloqueante, mover el archivo una vez completado se bloqueará. Es decir, request.body.moveTo(...) bloqueará la función del controlador hasta que se complete el movimiento. Esto significa que si varias de las 100 cargas se completan más o menos al mismo tiempo, el ExecutionContext interno de Play para el manejo de solicitudes puede sobrecargarse rápidamente. La API subyacente de moveTo también está en desuso en Play 2.3, ya que utiliza FileInputStream y FileOutputStream para copiar el FileInputStream TemporaryFile a una ubicación permanente. Los documentos le aconsejan usar la API de archivos de Java 7, ya que es mucho más eficiente.

Esto puede ser un poco crudo, pero algo más como esto debería hacerlo:

import java.io.File import java.nio.file.Files def upload = Action(parse.temporaryFile) { request => Files.copy(request.body.file.toPath, new File("/tmp/picture/uploaded").toPath) Ok("File uploaded") }

Dado este código de ejemplo de la documentación de Play:

def upload = Action(parse.temporaryFile) { request => request.body.moveTo(new File("/tmp/picture/uploaded")) Ok("File uploaded") }

  1. ¿Cómo se manejarán 100 solicitudes simultáneas de carga lenta (cantidad de subprocesos)?
  2. ¿Se cargará el archivo almacenado en la memoria o transmitido directamente al disco?