2012-08-09 5 views
5

Tengo una vista de Django que maneja los archivos cargados, y cuando se la llama repetidamente, siempre nos encontramos con errores de memoria. (Estamos en Heroku, por lo que obtenemos 512 mb de memoria por dyno web).Django: Los archivos cargados no son basura, causando problemas de memoria

Los errores de sobre memoria muestran que cada llamada aumenta el uso de memoria por el tamaño del archivo y el uso de la memoria nunca vuelve a bajar. Creo que el servidor lee la imagen en la memoria para guardarla en un modelo de Django, pero nunca la libera cuando termina.

Creo que debe haber una referencia a la imagen que persiste después de que la función retorna, evitando que la imagen sea recogida como basura. Pero no puedo pensar qué podría ser eso.

Aquí es una versión simplificada del código, que he probado para asegurarse de que tiene el mismo problema:

def simplified_add_image(request, biz_id): 
    if request.is_ajax(): 
     # the file is stored raw in the request 
     newBI = NewBusinessImage(business_id=biz_id, name=request.GET.get("name"), primary_image=True) 
     newBI.id = uuid.uuid4() 
     newBI.save() 
     uniquename = biz_id + ".." + get_a_uuid() + ".jpg" 

     newBI.original_image.save(uniquename, ContentFile(request.read())) 

     # this starts a series of tasks to process the image into various sizes. 
     # don't think it's the problem because it runs on a separate server, and the 
     # web server is the one that goes over memory 
     tasks.image_meta_task.delay(uniquename, newBI.id) 

     return StockJSONResponse(request, { 
      "success" : True, 
     }) 

me lo agradecería cualquier ayuda. ¡Muchas gracias!

arcilla

La siguiente es la información adicional que se solicita en los comentarios:

estamos almacenando los archivos en AmazonS3:

DEFAULT_FILE_STORAGE = 'storages.backends.s3boto.S3BotoStorage' 
STATICFILES_STORAGE = 'storages.backends.s3boto.S3BotoStorage' 
STATIC_URL = 'https://s3.amazonaws.com/%s/' % AWS_STORAGE_BUCKET_NAME 
from S3 import CallingFormat 
AWS_CALLING_FORMAT = CallingFormat.SUBDOMAIN 

Y aquí es el modelo NewBusinessImage

class NewBusinessImage(models.Model): 
    id = UUIDField(auto=True,primary_key=True,version=4, default=uuid.uuid4()) 
    business = models.ForeignKey('Business') 
    name = models.CharField(max_length=100) 
    original_image = models.ImageField(upload_to='photos/originals/') 
    thumbnail = models.ImageField(upload_to='photos/thumbnails/') 
    display_image = models.ImageField(upload_to='photos/displays/') 
    enlarged_image = models.ImageField(upload_to='photos/enlarged/') 
    num_views = models.PositiveIntegerField(editable=False, default=0) 
    primary_image = models.BooleanField(default=False) 
+0

¿Qué es esto 'image_meta_task.delay'? –

+0

es una tarea asíncrona apio , que se inicia en un servidor separado (no en mi servidor web), para procesar la imagen en tamaño estándar s y guardarlos. –

+0

Si esta es una versión simplificada, eso significa que si suelta 'image_meta_task.delay' ¿no tiene problemas de memoria? Además, ¿dónde almacena archivos? ¿Puedes publicar settings.py storege settings y 'NewBusinessImage'? – danihp

Respuesta

0

De acuerdo con la documentación de Django se envía con 2 manejadores de carga de archivos. Los controladores de memoria y el archivo temporal (Link to docs)

Si configura los ajustes de configuración FILE_UPLOAD_HANDLERS para incluir sólo "django.core.files.uploadhandler.TemporaryFileUploadHandler" nunca debería guardar el archivo en la memoria y técnicamente no causar los problemas de memoria que' está enfrentando en este momento.

Otra opción sería la de establecer el FILE_UPLOAD_MAX_MEMORY_SIZE a una pequeña cantidad que hará que la carga para ir directamente al disco.

Cuestiones relacionadas