2009-12-18 17 views
21

He escrito una aplicación de Google App Engine que genera programáticamente un montón de código HTML que es realmente el mismo resultado para cada usuario que inicia sesión en mi sistema, y ​​sé que esto va a ser en-eficiente cuando el código entra en producción. Por lo tanto, estoy tratando de encontrar la mejor manera de almacenar en caché las páginas generadas.Google App Engine - HTML generado en caché

La opción más probable es generar las páginas y escribirlas en la base de datos, y luego verificar la hora de la operación de puesta en la base de datos para una página dada en el momento en que se actualizó el código por última vez. Entonces, si el código es más reciente que el último puesto en la base de datos (para una solicitud HTML particular), se generará y servirá HTML nuevo, y se almacenará en caché en la base de datos. Si el código es anterior al último puesto en la base de datos, obtendré el código HTML directo de la base de datos y lo serviré (evitando así el desperdicio de CPU al generar el HTML). No solo estoy buscando minimizar los tiempos de carga, sino también minimizar el uso de la CPU.

Sin embargo, un problema que estoy teniendo es que no puedo averiguar cómo programar programicamente cuando se actualizó la versión del código cargado en el motor de la aplicación.

Estoy abierto a cualquier sugerencia sobre este enfoque, u otros enfoques para el almacenamiento en caché de html generado.

Tenga en cuenta que aunque Memcache podría ayudar en esta situación, creo que no es la solución final ya que solo necesito volver a generar html cuando se actualiza el código (en lugar de cada vez que expira memcache).

+5

Pero ... ¡para eso es Memcache! A menos que generar el HTML tome mucho, mucho tiempo, lo estás pensando demasiado. –

+0

Además, parece que el modelo de Memcache de App Engine solo almacena en caché los accesos al almacén de datos, no la generación de código: desde: http://code.google.com/appengine/docs/python/memcache/usingmemcache.html - Memcache es típicamente utilizado con el siguiente patrón: La aplicación recibe una consulta del usuario o la aplicación. La aplicación comprueba si los datos necesarios para satisfacer esa consulta están en Memcache. Si los datos están en Memcache, la aplicación usa esa información. Si los datos no están en Memcache, la aplicación consulta el almacén de datos y almacena los resultados en Memcache para futuras solicitudes. –

+2

@Alexander - Puedes poner lo que quieras en Memcache, lo que están mencionando es el caso de uso típico. –

Respuesta

6

Con el fin de velocidad:

  1. Memcache
  2. HTML en caché en el almacén de datos
  3. generación

Su solución de almacenamiento en caché de página completa debe tener esto en cuenta. Esencialmente, probablemente recomendaría usar Memcache de todos modos. En la mayoría de los casos, será más rápido que acceder al almacén de datos y cuando genere un bloque grande de HTML, uno de los principales beneficios del almacenamiento en caché es que posiblemente no tenga que incurrir en la penalización de E/S para acceder a los datos. almacenar. Si almacena en caché utilizando el almacén de datos, aún tiene la penalización de E/S. La diferencia entre regenerar todo y extraer de html almacenado en caché en el almacén de datos es bastante pequeña a menos que tenga una página muy compleja. Probablemente sea mejor obtener un montón de éxitos de caché muy rápidos de Memcache y regenerar por completo de vez en cuando que hacer una llamada al almacén de datos todo el tiempo. No hay nada que te impida invalidar el HTML en caché en Memcache cuando actualizas, y si tu tráfico es lo suficientemente alto como para garantizarlo, siempre puedes hacer un sistema de almacenamiento en caché de niveles múltiples.

Sin embargo, mi principal preocupación es que se trata de una optimización prematura. Si todavía no tiene el tráfico, mantenga el almacenamiento en caché al mínimo. App Engine proporciona un conjunto de herramientas de análisis de rendimiento realmente prácticas, y usted debe usarlas para identificar los cuellos de botella después de que tenga al menos algunas QPS de tráfico.

Cada vez que realice la optimización del rendimiento, ¡mida primero! Muchas de las "optimizaciones" de rendimiento resultan ser más lentas que las originales, exactamente iguales, o tienen características de experiencia de usuario negativas (como datos obsoletos). No optimices hasta que estés seguro de que debes hacerlo.

+0

Hola Bob, ¡Gracias por tu respuesta! ¡Tomará en cuenta tus sugerencias! –

+0

definitivamente benchmark memcached si quiere poner grandes cantidades de datos en él. en el motor de la aplicación, todo se encuadra con una implementación pura de Python, esto * podría * terminar bastante lento. – tosh

+0

Si el objeto que está insertando es HTML sin procesar previamente, eso no debería importar. –

1

Esta no es una solución completa, pero podría ofrecer una opción interesante para el almacenamiento en caché.

Google Appengine Frontend Caching le permite una forma de almacenamiento en caché sin utilizar Memcache.

1

sólo sirven una versión estática de su sitio

En realidad es mucho más fácil de lo que piensa.

Si ya tiene un archivo que contiene todas las URL de su sitio (ex urls.py), la mitad del trabajo ya está hecho.

Aquí está la estructura:

+-/website 
+--/static 
+---/html 
+--/app/urls.py 
+--/app/routes.py 
+-/deploy.py 

/html es donde los archivos estáticos se servirán a partir. urls.py contiene una lista de todas las URL para su sitio. routes.py (si movió las rutas fuera de main.py) tendrá que modificarse para que pueda ver la versión generada dinámicamente localmente pero sirva la versión estática en producción. deploy.py es su generador de sitios estáticos de una sola parada.

Depende del diseño de su módulo de urls. Personalmente lo uso como una ventanilla única para buscar todos los metadatos de una página, pero YMMV.

Ejemplo:

main = [ 
    { 'uri':'about-us', 'url':'/', 'template':'about-us.html', 'title':'About Us' } 
] 

Con todas las direcciones URL de la página en un formato estructurado que facilita el rastreo de su propio sitio muy fácil.

La configuración de la ruta es un poco más complicada. No voy a entrar en detalles porque hay demasiadas formas diferentes en que esto podría lograrse. La pieza importante es el código requerido para detectar si se está ejecutando en un servidor de desarrollo o producción.

Aquí está:

# Detect whether this the 'Development' server 
DEV = os.environ['SERVER_SOFTWARE'].startswith('Dev') 

prefiero poner esto en main.py y exponerlo a nivel mundial porque yo lo uso para encender/apagar otros cosas como la tala, pero, una vez más, tu caso es distinto.

pasado, lo que necesita el rastreador/compilador:

import os 
import sys 
import urllib2 
from app.urls import main 

port = '8080' 
local_folder = os.getcwd() + os.sep + 'static' + os.sep + 'html' + os.sep 
print 'Outputting to: ' + local_folder 

print '\nCompiling:' 
for page in main: 
    http = urllib2.urlopen('http://localhost:' + port + page['url']) 
    file_name = page['template'] 
    path = local_folder + file_name 
    local_file = open(path, 'w') 
    local_file.write(http.read()) 
    local_file.close() 
    print ' - ' + file_name + ' compiled successfully...' 

Esto es realmente cosas rudimentaria. De hecho, me sorprendió lo fácil que fue cuando lo creé. Esto es literalmente el equivalente a abrir su sitio página por página en el navegador, guardar como html y copiar ese archivo en la carpeta/static/html.

La mejor parte es que la carpeta/html funciona como cualquier otra carpeta estática, por lo que se almacenará automáticamente en caché y la caducidad de la caché será la misma que la del resto de los archivos estáticos.

Nota: Esto maneja un sitio donde todas las páginas se sirven desde el nivel de la carpeta raíz. Si necesita anidar más profundamente las carpetas, necesitará una pequeña modificación para manejar eso.

+0

Hola Evan. Si bien es útil, su respuesta hace suposiciones potencialmente incorrectas sobre el entorno de Alex. Si está creando un sistema de administración de contenido donde los administradores pueden editar el contenido, independientemente de la aplicación, entonces el uso de archivos estáticos obviamente no resolverá este problema. Considere evitar respuestas que en realidad no respondan la pregunta. Algunos miembros de la comunidad rechazarán esos. Si sabe cómo almacenar en caché el código HTML generado, le recomiendo que elabore más. Aún así, creo que esta es información útil, especialmente los pasos para convertir HTML generado en HTML estático a través de la fuente del navegador. – jmort253

+0

@ jmort253 En realidad, es completamente posible editar el contenido y mostrarlo dinámicamente en el servidor de desarrollo. Idealmente, enviar contenido al servidor de producción implica un ciclo de compilación/implementación de 1 clic. Las rutas dinámicas (es decir, las instalaciones de edición/administración) y los archivos dinámicos del sitio están disponibles en el servidor de desarrollo, mientras que el servidor de producción apunta a la versión estática (es decir, estática/html) del sitio. En cuanto a la producción, todo permanece estático, por lo que todo se almacena en caché automáticamente. –

+0

(cont) Esto puede no ser un enfoque estándar/tradicional, pero funciona. Actualmente lo estoy usando para 2 sitios donde el servidor de desarrollo es GAE y la producción es Apache (es decir, usa rutas de expresiones regulares para establecer la estructura de archivos correcta). Lo mismo se puede hacer para una configuración de producción/desarrollo GAE todo en uno y los números de versión permanecerán sincronizados si el compilador está configurado para disparar como un gancho de despliegue de GAE. Consulta https://developers.google.com/appengine/articles/hooks. La mejor forma de minimizar los ciclos de la CPU es nunca lanzar un código dinámico en producción ... –

1

Tema viejo, pero comentaré de todos modos como la tecnología ha progresado un poco ... Otra idea que puede o no ser apropiada para usted es generar el HTML y almacenarlo en Google Cloud Storage. Luego acceda al HTML a través de un enlace CDN que el almacenamiento en la nube le brinda. No es necesario comprobar Memcache o esperar a que el almacén de datos se despierte con nuevas solicitudes. He empezado a almacenar todo mi JavaScript, CSS y otro contenido estático (imágenes, descargas, etc.) como este para mis aplicaciones appengine y funciona bien para mí.

+1

Para agregar a esto, la entrada/salida entre servicios en la nube dentro de la misma región es gratuita: https://cloud.google.com/storage/pricing. Entonces, mientras no permita que el usuario acceda directamente, solo está pagando por el almacenamiento. Esto podría ser preferible si no quiere perder el ancho de banda de Memcache en sus activos estáticos. –