debug_mode=ON

Buscar en

 
 

Cómo resolvimos los problemas de carga

Escrito por debugmodeon hace 1 años bajo una licencia de Creative Commons Creative Commons License
1196 visitas. Etiquetas: gae, app-engine, debugmodeon

Cuando recibimos el pico de visitas provenientes de barrapunto.com nos ocurrió lo que les ha ocurrido a muchos usuarios de Google App Engine: problemas de "over quota". El servicio Google App Engine tiene unas cuotas diarias muy generosas. Sin embargo impone una cuota también a cada petición de forma independiente. Nuestro problema es que estábamos superando el uso de CPU por petición en algunas URLs. ¿Cómo lo resolvimos?

Cachear, cachear, cachear

Utilizamos memcache para no tener que consultar contínuamente el datastore. Bueno, realmente ya utilizábamos memcache días antes, pero ahora tuvimos que hacer un uso aún más intensivo.

Servir las imágenes de usuarios y grupos consumía mucha CPU. También los feeds RSS. Cacheamos todas esas consultas. Nos creamos una sencilla función de utilidad:

def cache(self, key, function, timeout=0):
    data = memcache.get(key)
    if data is not None:
        return data
    else:
        data = function.__call__()
        memcache.add(key, data, timeout)
        return data

Si antes obteníamos información con:

resultado = self.obtener_resultado()

Ahora hacemos...

resultado = self.cache('clave', self.obtener_resultado)

Cambiar el sistema de plantillas

Cachear los resultados disminuyó de forma importante el consumo de CPU por petición. Sin embargo seguía siendo elevado y los problemas de over quota no cesaban. Nos comentaron que quizá el motor de plantillas django era problemático. Hicimos varias pruebas de carga con jinja2, un motor de plantillas similar al de django, pero no completamente compatible. Las pruebas indicaban que con jinja2 obteníamos una mejora de rendimiento a tener en cuenta. Por lo tanto decidimos migrar a jinja2.

Desnormalizar

Sin embargo los problemas persistían. No sabíamos cómo optimizar aún más. No comprendíamos cómo la página principal podía consumir tanta CPU si sólo estábamos usando cuatro consultas sencillas y perfectamente cacheadas...

Finalmente encontramos el problema. Estábamos cacheando listas de resultados, pero en la plantilla estábamos navegando por las relaciones de estos resultados, lo que provocaba que se hiciera una consulta por resultado. Con 30 resultados a mostrar, aunque estuvieran cacheados, al navegar por sus relaciones estábamos provocando 30 consultas a la base de datos. Por ejemplo esto era lo que hacíamos en la lista de últimos mensajes en los foros:

{{ thread.author.nickname }}

Desnormalizamos la base de datos y ahora hacemos lo siguiente:

{{ thread.author_nickname }}

Ahora un mensaje de un foro guarda no sólo una referencia al autor, sino también el nickname del mismo. Es decir, añadimos redundancia a los datos, poniendo el nickname del autor en otros objetos. Debido a que un usuario no puede cambiar su nickname y que el autor de un mensaje evidentemente tampoco cambia, fue una desnormalización sencilla.

Después de esta optimización cesaron casi todos los errores. Optimizamos alguna cosa más, pero las anteriores fueron las optimizaciones claves.

No hemos tenido problemas de over quota desde entonces. Estamos muy contentos y hemos aprendido mucho.

Google Developer Day

Hicimos nuestras últimas optimizaciones aprovechando el tiempo que brindaban los talleres del Google Developer Day. Sí, íbamos contra el tiempo, no parábamos :P. Allí hablamos con los ingenieros de Google y les enseñamos la aplicación. Resulta que nuestra web es una de las aplicaciones más grandes que hay actualmente funcionando sobre App Engine. Revisaron nuestra cuenta en el servicio y creemos que fueron generosos dándonos mayor márgen de maniobra en nuestra cuota de servicio. Aunque no lo sabemos a ciencia cierta.

Más optimizaciones

Tenemos algunas optimizaciones más en mente. Por ejemplo, en la URL de las imágenes de usuarios y grupos vamos a incluir un número que indicará la versión de la imagen. Haremos que el navegador cachée todas las imágenes. Que las descargue una vez y nunca más las vuelva a solicitar. Cuando un usuario o un grupo cambie su imágen, el número de versión cambiará, y por tanto la URL también. Para el navegador será una nueva imagen que nunca ha visitado.

 

¡Votalo! 6 votos
¡Compártelo!

        

&nbps;

&nbps;

debugmodeon

Sobre debugmodeon

debug_mode=ON es el administrador de esta página. Realmente no es una persona, sino que somos todos los que estamos detrás de esta página. Ante cualquier duda o sugerencia procuraremos responder lo mejor y más rápido posible :)

 
Regístrate o haz login para participar.
¿Todavía no conoces debugmodeon?
debugmodeon es la red social para profesionales de la informática
descubre debugmodeon
 

1 comentarios en "Cómo resolvimos los problemas de carga"

AbeEstrada
AbeEstrada escribió
hace 1 años

#1   

Pues felicidades y se me hace curioso lo de las plantillas de Django, se me hace que no es precisamente que den problema si no mas bien que consumen mas recursos que las de Jinja. Aun asi, felicidades por la excelente aplicacion que han creado.

 
 
 
 

© Copyright 2008-2009 debug_mode=ON | Aviso legal | Contacto | FAQ | ¿Quiénes somos? |