Estoy totalmente de acuerdo tanto con Toby como con John Vasileff: S3 es ideal para descargar objetos multimedia grandes si puede tolerar los problemas asociados. (Una instancia de la propia aplicación hace eso para 10-1000MB FLV y MP4.) P. ej .: Sin solicitudes parciales (encabezado de rango de bytes), sin embargo. Uno tiene que manejar ese 'manual', tiempo de inactividad ocasional, etc.
Si esa no es una opción, el código de John se ve bien. Descubrí que un búfer de bytes de 2k FILEBUFFERSIZE es el más eficiente en marcas de microbancos. Otra opción podría ser un FileChannel compartido. (FileChannels es seguro para subprocesos.)
Dicho esto, también agregaría que adivinar qué causó un error de falta de memoria es un error de optimización clásico. Mejorará sus posibilidades de éxito trabajando con métricas duras.
- Lugar -XX: + HeapDumpOnOutOfMemoryError en ustedes parámetros de inicio de JVM, por si acaso
- tomar el uso jmap en la JVM en ejecución (jmap -histo <pid>) bajo carga
- analyize las métricas (jmap -histo out put, o haz que jhat mire tu volcado de heap). Es muy posible que tu falta de memoria provenga de algún lugar inesperado.
Por supuesto, hay otras herramientas por ahí, pero jmap & jhat vienen con Java 5+ 'fuera de la caja'
He pensado en escribir el archivo en una unidad temporal local y luego generando otro hilo para manejar la transmisión, de manera que el hilo del servlet de tomcat pueda reutilizarse. Parece que sería demasiado pesado.
Ah, no creo que no puedas hacer eso. E incluso si pudieras, suena dudoso.El hilo de tomcat que está administrando la conexión necesita tener el control. Si está pasando hambre en el hilo, aumente la cantidad de hilos disponibles en ./conf/server.xml. De nuevo, las métricas son la forma de detectar esto, no adivinen.
Pregunta: ¿También se está ejecutando en EC2? ¿Cuáles son los parámetros de inicio de JVM de tu tomcat?
Hmm, dado que no se establece una longitud de contenido, el contenedor de servlets debe almacenar en búfer porque necesita establecer el encabezado de longitud del contenido antes de que pueda transmitir cualquier dato. Entonces, ¿no estás seguro de la cantidad de memoria que guardas? –
Peter, si no puede dirigir a los usuarios directamente a una URL de servicio en la nube y desea establecer el encabezado de longitud de contenido, y aún no conoce el tamaño, y no puede consultar el tamaño del servicio en la nube, entonces supongo La mejor opción es transmitir primero a un archivo temporal en el servidor. Por supuesto, guardar una copia en el servidor antes de enviar el primer byte al cliente puede hacer que el usuario piense que la solicitud falló en función de la duración de la transferencia cloud -> server. –
@PeterKriens el encabezado content-length no es obligatorio. también, puede usar transferencias fragmentadas donde solo necesita especificar la longitud de un fragmento. – bluesmoon