2012-07-18 14 views
5

Estoy usando heroku para alojar una aplicación web con el objetivo principal de alojar videos. Los videos están alojados a través de vimeo pro, y estoy usando el vimeo gem by matthooks para ayudar a manejar el proceso de carga. La carga funciona para archivos pequeños, pero no para archivos más grandes (~ 50mb, por ejemplo).Cómo cargar archivos grandes en Heroku (particularmente videos)

Un vistazo a los registros de heroku muestra que estoy obteniendo el error http 413, que significa "Entidad de solicitud demasiado grande". Creo que esto podría tener que ver con un límite que heroku coloca en las cargas de archivos (más de 30mb, according to this webpage). El problema es que cualquier información que pueda encontrar sobre el tema parece estar desactualizada y en conflicto (como esta página que claims there is no size limit). Tampoco pude encontrar nada en el sitio de heroku sobre esto.

He buscado en google y encontré algunas páginas algo relevantes (one y two), pero ninguna solución me funcionó. La mayoría de las páginas que encontré se refieren a la carga de archivos de gran tamaño a Amazon s3, que es diferente de lo que estoy tratando de hacer.

Aquí está la salida correspondiente de los registros:

2012-07-18T05:13:31+00:00 heroku[nginx]: 152.3.68.6 - - [18/Jul/2012:05:13:31 +0000] 
    "POST /videos HTTP/1.1" 413 192 "http://neoteach.com/components/19" "Mozilla/5.0 
    (Macintosh; Intel Mac OS X 10.7; rv:13.0) Gecko/20100101 Firefox/13.0.1" neoteach.com 

no hay otros errores en los registros. Este es el único resultado que aparece cuando intento subir un video que es demasiado grande. Lo que significa que esto no es un error de tiempo de espera o un problema al exceder la memoria asignada por dyno.

¿Heroku realmente impone un límite en los tamaños de carga? Si es así, ¿hay alguna forma de cambiar este límite? Tenga en cuenta que los archivos en sí no se están almacenando en los servidores de heroku, simplemente se pasan a los servidores de vimeo.

Si el problema no es el límite en los tamaños de carga, ¿alguien tiene una idea de qué más podría estar yendo mal?

Muchas gracias!

+0

Por lo que sé, no hay tal manera. Tuve que subir directamente a S3. Es posible que puedas encontrar la forma de pasar los videos directamente a Vimeo, pero el único resultado que encontré no fue muy alentador: http://vimeo.com/forums/topic:28113 – Qsario

+0

Merece la pena señalar, acabo de probar cargando un archivo de 8.5MB a mi aplicación Heroku, que tardó 3 minutos y 15 segundos (sí, tengo DSL). Tengo 'web: gunicorn -t 60 -k" eventlet "-w 3 myapp.wsgi: application' en mi' Procfile'. En otras palabras, aumenté mi tiempo de espera a 60 segundos y mi aplicación permitirá que una carga demore más de 3 minutos. No estoy seguro de la razón para esto, pero tiene algo que ver con que mi Dyno permita conexiones simultáneas. – orokusaki

Respuesta

4

Actualización:

OP aquí. Todavía no estoy exactamente seguro de por qué estaba obteniendo este error 413 en particular, pero pude encontrar una solución que funciona con la gema s3_swf_upload. La implementación involucra flash, que es menos que ideal, pero fue la única solución (de 3 o 4 que probé) en la que pude trabajar.

Como señaló Neil (¡gracias Neil!), El error que debería haber estado recibiendo es "H12 - Request timeout". Y terminé encontrando este error después de repetidas pruebas.El problema ocurre cuando intentas cargar archivos grandes al servidor heroku desde tu controlador (usando un banco de datos web), ya que el servidor tarda demasiado en responder a la solicitud posterior.

El enfoque correcto es enviar el archivo directamente a s3 sin pasar por heroku.

He aquí una descripción de alto nivel de mi enfoque:

  1. Utilice la gema s3_swf_upload para suministrar un formulario de carga directa a S3.
  2. Detecta cuando el archivo termine de cargarse con la función de devolución de llamada javascript proporcionada en la gema.
  3. Usando javascript, envíe a los rieles un mensaje de mensaje para que su servidor sepa que el archivo se ha terminado de cargar.
  4. El controlador que responde a la publicación javascript hace dos cosas: (a) asigna un atributo s3_key al objeto de video (servido como un parámetro en el formulario). (b) inicia una tarea en segundo plano utilizando la gema delayed_job.
  5. La tarea en segundo plano recupera el archivo de s3. Usé la gema aws-sdk para lograr esto, porque ya estaba incluida en s3_swf_upload. Tenga en cuenta que esto es claramente diferente de la gema aws-s3 (de hecho, entran en conflicto entre sí).
  6. Después de recuperar el archivo de s3, utilicé la gema vimeo para cargarlo en vimeo (todavía en segundo plano).

La implementación anterior funciona, pero no es perfecta. Para archivos de cerca de 500 MB de tamaño, aún se encontrará con errores R14 en sus dineros de trabajador. Esto ocurre porque heroku solo asigna 512MB de memoria por dyno, por lo que no puede cargar todo el archivo en la memoria a la vez. La forma de solucionar este problema es implementar algún tipo de fragmentación en el paso final, donde recupera el archivo de s3 y lo sube a vimeo pieza por pieza. Todavía estoy trabajando en esta parte, y me gustaría escuchar cualquier sugerencia que pueda tener.

Esperemos que esto pueda ayudar a alguien. No dude en hacerme cualquier pregunta. Como dije, mi solución no es perfecta, así que puede agregar su propia respuesta si cree que podría ser mejor.

+0

Mire "Carrierwave" con "Fog" y "CarrierwaveDirect" – Narfanator

+0

¡Es útil, gracias! –

2

Su mayor problema no es el tamaño de los archivos aquí, sino el hecho de que espera que el usuario cargue archivos grandes a Heroku, y luego los pase. El problema aquí es que todas las solicitudes en la plataforma Heroku deben devolver el primer byte en 30 segundos, lo que en su caso es muy poco probable.

Por lo tanto, debe considerar hacer que los usuarios suban directamente a S3/Vimeo/whereever y luego conectar los datos de su aplicación a estos activos cargados.

Si está usando Ruby, entonces la gema directa de onda transportadora puede valer la pena para ver cómo se hace. En su defecto, existen servicios de terceros que le permiten hacer esto a través de un código que puede incluir en la página, pero estos tienen un costo adjunto.

+0

Gracias Neil, el problema que describí anteriormente no parece ser un tiempo de espera. No hay "H12 - Tiempo de espera de solicitud" en los registros.Sin embargo, entiendo que el tiempo de espera es un gran riesgo con las grandes cargas de archivos, así que buscaré cargas directas. Quizás eso también resolverá el problema anterior. – stephenalexbrowne

+0

Debería. Supongo que has estado probando una conexión decente hasta ahora. –

+0

Solo cuando una conexión está inactiva durante 30 segundos, se agota el tiempo de espera. –

2

Creo que la mejor opción aquí es cargar directamente a S3. Es mucho más económico y mucho más seguro que permitir a los usuarios subir archivos a su propio servidor (o Heroku en este caso). También es un patrón bien probado utilizado por muchas plataformas de alojamiento de videos (sé que esto lo hacen).

Mira la jQuery subir plugin, que acepta la subida directos a S3: https://github.com/blueimp/jQuery-File-Upload

También puedes ver los Railscasts en torno a este tema: # 381 y # 383.

Cuestiones relacionadas