Optimizando la Performance de Plone

Document Actions
Send this page to somebody Print this page

Note: This is the print view with all the tutorial pages on one page. The paginated version is available here, if you prefer that.

Este tutorial le mostrara un modo simple y eficaz de usar caching para hacer de su Sitio Plone un sistema digno de producción capaz de administrar 100 páginas por segundo con un hardware apropiado (En progreso)

Introducción, objetivos y créditos

Que es lo que este tutorial cubre y no cubre y quien es el responsable de esto.

En este tutorial, nosotros le enseñaremos como cachear su sitio Plone de una buena manera para hacer este sensible y rápido para usuarios anónimos que visiten su sitio.

La estrategia presentada es simple y eficiente, pero tiene algunas advertencias, y no es la bala mágica de plata para solucionar cualquier problema de funcionamiento que usted pueda tener. Muy a menudo, los problemas de funcionamiento en sitios Plone son causados por configuraciones impropias de Plone, o el servidor sobre el que se esta corriendo, o productos de tercero mal escritos. Es importante saber que hay más aspectos que tienen que ser tenidos en cuenta cuando optimizamos el funcionamiento de un sitio Plone.

Este tutorial apunta a cubrir lo siguiente:

  • Configurar un servidor web delante de Plone que pueda cachear elementos que han sido marcados para ser cacheables - por lo tanto no sobrecargan la instancia Plone en lo absoluto - pero son luego servidos por el servidor web cacheado delante de este.  Esto es especialmente eficiente para el acceso a archivos, CSS y Javascripts, pero usted también puede aplicar esto a paginas enteras si usted necesita servir paginas extremadamente rápidas.
  • Configurar un virtual host diferente sin cacheado para el uso de editores.

Créditos

Apache 1.3 configuración fue originalmente escrita por Seb Potter y fue adaptada para las versiones actualizadas de Plone y Zope por Alexander Limi.

Elementos comunes para cachear

Una breve explicación acerca de que vamos a configurar.

Plone es un sistema muy complejo. Donde un sitio HTML plano sólo puede tomar un centésimo de un segundo para cargar de un servidor. La main page de Plone es totalmente dinámica.

Agregando en el tope el hecho de que, incluyendo javascript y css el tamaño de la página excede los 100KB y puede tomar más de 30 segundos en descargarse, esto nos puede hacer pasar por una experiencia bastante lenta. Obviamente, si tienes más de un par de usuarios en tu sitio a la vez, este será inusable.

Esas son las malas noticias.

Sin embargo, esto no es del todo malo. La aplicación Zope que es la base de Plone nunca fue pensada para ser un servidor de web. Afortunadamente, podemos utilizar Apache as a front-end web server para manejar todas las conexiones tediosas de la web a través de un proceso llamado reverse proxying.

Configurar un reverse proxy es bastante fácil. Primero, configure Zope para que este no este corriendo en el puerto 80. Por defecto, Zope corre en el puerto 8080, pero algunos instaladores y distribuciones usan otros puertos - entonces sustituya 8080 por cual sea el puerto en que este corriendo su instancia. Lo importante aquí es que este no debería estar corriendo en el puerto 80, donde vamos a agregar el servidor web que debería estar delante de Plone.

Pruebe esto accediendo a su sitio en http://tusitio.com:8080.

Para poner el proxying a trabajar, usted tiene que añadir un Virtual Host Monster a la carpeta raíz de su instalación Zope. Llámele a esta como usted quiere, pero debe ser añadida a la raíz de su Zope, y no en la raíz de su sitio Plone.

Solo Plone 2.0: Si usted esta corriendo Plone 2.0.x, tendrá que editar también el template portal_skins/plone_templates/global_cache_settings para prevenir a Plone de enviar un Pragma: no-cache HTTP header. Por defecto para aliviar el desarrollo, Plone fue configurado para deshabilitar todos los HTTP caching.

Simplemente localice el template en su sitio Plone a través del ZMI, y customiselo en su carpeta de custom skin. Ahora, edite el template de modo que el contenido sea:

<metal:cacheheaders define-macro="cacheheaders">
<metal:block tal:define="dummy python:request.RESPONSE.setHeader('Content-Type', 'text/html;;charset=%s' % charset)" />
<metal:block tal:define="dummy python:request.RESPONSE.setHeader('Content-Language', lang)" />
<metal:block tal:define="dummy python:request.RESPONSE.setHeader('Expires', 'Sat, 1 Jan 2000 00:00:00 GMT')" />
</metal:cacheheaders>
Usted esta ahora listo para configurar el servidor web.

Caching configuración utilizando Apache 1.3

Como dejar el servidor listo para cachear - usando Apache 1.3.

Asegúrese de tener instalado un servidor web Apache. Esta configuración en particular está basada en Apache 1.3. Para otros servidores de web, mirar las siguientes páginas en este tutorial.

Asegúrese que Apache esta corriendo sobre el puerto 80 para comprobar esto puede ver la página por defecto de Apache en http://site.com.

Debemos editar el archivo de configuración de Apache (normalmente localizado en /etc/httpd/conf/httpd.conf - si usted no sabe donde se encuentra el archivo de configuración, usar locate httpd.conf), ahí hay algunas cosas que  usted tendrá que checkear:

  • Asegúrese que mod_proxy esta habilitado. Busque la lista de módulos cargados para libproxy.so, y asegure que las siguientes líneas no están comentadas:
      LoadModule proxy_module modules/libproxy.so
    AddModule mod_proxy.c
  • Configurar un VirtualHost para su nombre de dominio que use un reverse-proxy en orden de pasar las peticiones a través de Zope. El siguiente ejemplo puede ser copiado y pegado en la parte de más abajo de su archivo de configuración, y usted solo tendrá que editar un par de líneas:
    <VirtualHost *>

    # A sample VirtualHost section for using Apache as a webserver
    # instead of Zope.
    # ServerName is the url of your website.

    ServerName site.com

    # Add serverAlias lines for other domain names that should
    # point to this website. They will be rewritten by Apache to
    # the ServerName, so that anyone going to www.site.com
    # will be invisibly redirected to site.com in their browser.

    ServerAlias www.site.com

    # ServerAdmin is your email address, which shows up on error
    # pages when Apache cannot connect to Zope.

    ServerAdmin webmaster@site.com

    # The ProxyPass and ProxyPassReverse lines are the magic
    # ingredients. They rewite requests to http://site.com and
    # pass the entire request through to Zope on
    # http://site.com:8080. The VirtualHostBase ensures that
    # when the page goes back to the browser, it goes out through
    # Apache, and appears to have come from http://site.com.

    # The line is made up from:

    # ProxyPass or ProxyPassReverse

    # / is the url at http://site.com that you wish to use to
    # point to the Zope site. You could keep http://site.com as a
    # flat HTML site in Apache, and replace / with /zope to make
    # http://site/com/zope point to your zope site.
    # http://site.com:8080 is the address that your zope is
    # running on.

    # /VirtualHostBase/http/site.com:80 makes sure that zope
    # *thinks* it is running at http://site.com instead of at
    # http://site.com:8080. You don't have to do anything else
    # in Zope to make this work.

    # /yourplonesite is the location of your Plone Site within Zope.
    # If you added a Plone Site into the root of your Zope with an id
    # of 'mysite', then you just change this bit to /mysite

    # /VirtualHostRoot/ makes your Plone site think it is the root of the site.

    ProxyPass / http://site.com:8080/VirtualHostBase/http/site.com:80/plonesite/VirtualHostRoot/
    ProxyPassReverse / http://site.com:8080/VirtualHostBase/http/site.com:80/plonesite/VirtualHostRoot/
    </VirtualHost>
Ahora reinicie Apache y debería encontrar que http://site.com es ahora su sitio web Plone. (Si tiene algún problema, asegúrese que libproxy.so esta presente en el directorio /etc/httpd/modules/.)

Ahora usted tiene una configuración respetable: Apache esta sirviendo las peticiones web y Zope es un servidor backend. Como bonus, también tiene un virtual hosting completamente configurado, por lo tanto puede correr múltiples sitios diferentes con múltiples dominios diferentes sobre un solo servidor con una sola dirección de IP. Todo lo que necesita hacer es duplicar y editar esa sección del VirtualHost por cada sitio.

Usted quería tomar nota sobre que tan rápido esta corriendo esta configuración hasta este punto. Notar que no hemos ganado ninguna verdadera ventaja de velocidad aun, nosotros solo hemos puesto los fundamentos para esto. En una terminal, usar la aplicación Apache Benchmark para probar la velocidad del sitio. La aplicación se encuentra normalmente en '/usr/sbin/ab':
 /usr/sbin/ab -n 100 http://yoursite.com/
Esto va a pedir consecutivamente 100 solicitudes a su servidor. Usted debería notar que todas las solicitudes toman cerca de 0.5 a 1.0 segundos, con no mucha discrepancia. Mientas esto no parece tan malo para una pagina dinámica, recuerde que esto es solo el HTML. Para una página completa con CSS, Javascript e imágenes el tiempo de procesamiento puede ser mucho mas largo.

La salida típica podría parecerse a esto:
 Benchmarking site.com (be patient).....done
Server Software: Zope
Server Hostname: site.com
Server Port: 80

Document Path: /
Document Length: 32560 bytes

Concurrency Level: 1
Time taken for tests: 68.901 seconds
Complete requests: 100
Failed requests: 0
Broken pipe errors: 0
Total transferred: 3293500 bytes
HTML transferred: 3256000 bytes
Requests per second: 1.45 [#/sec] (mean)
Time per request: 689.01 [ms] (mean)
Time per request: 689.01 [ms] (mean, across all concurrent requests)
Transfer rate: 47.80 [Kbytes/sec] received
Entonces, que podemos hacer para hacerlo mas rapido?

Lo primero que podemos hacer es permitir a Apache que cache el resultado de las páginas. Esto puede hacerse porque configuramos Apache para ser el servidor front-end, nosotros en realidad hemos creado un caching reverse-proxy, lo que significa que todas las páginas que produce Zope son ahora llevadas de nuevo afuera al navegador a través de Apache y pueden ser cacheadas para incrementar dramáticamente el funcionamiento. Solo que aun no le hemos dicho a Apache que cache algo aun.

Para dejar que Apache conozca que deseamos cachear contenido con un cierto tiempo de expiración, el archivo mod_expires debe ser instalado. Compruebe su directorio de módulos de Apache (normalmente /etc/httpd/modules) para mod_expires.so, y luego asegúrese de tener las siguientes líneas en el archivo de configuración de su Apache:
 LoadModule expires_module modules/mod_expires.so
AddModule mod_expires.c
Al final de la sección VirtualHost, justo antes de </VirtualHost> añadir las siguientes líneas:

 # CacheRoot is the location on the filesystem to store files that 
# Apache caches. This directory must be created, and the user that
# Apache runs as must have full write permissions to it.
# It's a bad idea to create this in the /tmp directory, as the
# directory itself will then be deleted when you reboot.
CacheRoot "/var/cache/site.com"

# CacheSize determines how big this cache can get in KB. It's a
# good idea that this number is about 30% less than the available
# space in the CacheRoot directory. Here we choose to cache 10MB
# of data, which is enough for a personal website, but not for
# anything larger.
CacheSize 10000

# CacheGcInterval specifies how often (in hours) to examine the
# cache and delete obsolete files.
CacheGcInterval 2

# CacheLastModifiedFactor allows the estimation of an expiry date
# for a page if it doesn't have an expiry-date specified in the
# HTTP headers returned from Zope. This is based on (time since
# last modification * CacheLastModifiedFactor), so that content
# that is ten hours old would be given an expiry date of 1 hour in
# the future.
CacheLastModifiedFactor 0.1

# CacheDefaultExpire sets a default expiry time of 1 hour into the
# future for cached pages.
CacheDefaultExpire 1

# CacheDirLength sets the number of characters used in directory
# names for subdirectories of CacheRoot
CacheDirLength 2

# The following definitions set expiry times for various content
# types. In this list, each content type defined is cached for a
# maximum period of 1 hour (3600 seconds) before it must be checked
# again. Non-listed content types are not cached.

ExpiresActive On
ExpiresByType image/gif A3600
ExpiresByType image/png A3600
ExpiresByType image/jpeg A3600
ExpiresByType text/css A3600
ExpiresByType text/javascript A3600
ExpiresByType application/x-javascript A3600
ExpiresByType text/html A3600
ExpiresByType text/xml A3600
Una vez que usted ha terminado de añadir esto a la sección VirtualHost, guardar el archivo config. Ahora, entre a su carpeta /var/cache, cree el directorio definido como CacheRoot en la configuración que usted acaba de editar  y haga este escribible para el usuario apache. En el caso de nuestro ejemplo, esto seria:
 mkdir /var/cache/site.com
chown -R apache:apache /var/cache/site.com
Ahora reinicia Apache para asegurarnos que estos cambios han tenido efecto:
apachectl graceful
Hasta este punto, aunque Apache sea capaz de realizar caching, ninguna de sus páginas en realidad están siendo cacheadas. Podemos probar esto usando wget y mostrando los HTTP Response headers:
 wget -sS --delete-after http://site.com/

--03:16:51-- http://site.com/
=> `index.html'
Resolving site.com... done.
Connecting to site.com[127.0.0.1]:80... connected.
HTTP request sent, awaiting response...
1 HTTP/1.1 200 OK
2 Date: Mon, 19 Jan 2004 03:16:51 GMT
3 Server: Zope/(unreleased version, python 2.3.2, linux2) ZServer/1.1 Plone/2.0-RC3
4 Vary: Accept-Encoding
5 Content-Length: 32560
6 Content-Language:
7 Expires: Mon, 19 Jan 2004 04:16:52 GMT
8 Etag:
9 Cache-Control: max-age=3600
10 Content-Type: text/html;charset=utf-8
11 X-Cache: MISS from site.com
12 Connection: close
Note el X-Cache header mostrando un cache MISS. Mientras nosotros esperamos esto la primera vez que llamamos una página (como esto aún no ha sido cacheada), ahora esperaríamos llamadas subsecuente a aquella página si el caching esta trabajando de manera correcta.


Su sistema esta ahora en el punto donde es totalmente capaz de cachear contenido y todo lo que resta por hacer es decirle a su Accelerated HTTP Cache Manager en su sitio Plone que es lo que debería cachear.

Caching configuración utilizando Apache 2.0

Como configurar el cachedo utilizando Apache 2.0.

Las mayores diferencias de las instrucciones de Limi sobre Apache 1.3 fueron:

  • En orden de obtener las peticiones del apache proxying las siguientes líneas deben ser descomentadas en el httpd.conf:
      LoadModule proxy_http_module modules/mod_proxy_http.so
  • Los siguientes módulos son además necesarios para hacer funcionar el caching. Estos pueden no aparecer en su httpd.conf por lo tanto si no aparecen usted deberá agregarlos:
      LoadModule disk_cache_module modules/mod_disk_cache.so
    LoadModule cache_module modules/mod_cache.so
  • La siguiente configuración en el archivo httpd.conf no fue suficiente:
      CacheRoot "/var/cache/artpropensity.com"
    Esta debe ser procesada por: CacheEnable disk / por lo tanto esta luce como:
      CacheEnable disk /
    CacheRoot "/var/cache/artpropensity.com"
  • Además tuve que setear de manera explicita los IP y hosts en mi archivo /etc/hosts, como en:
      192.168.10.10 www.artpropensity.com artpropensity.com
    Esto es de modo que los ajustes siguientes en el archivo httpd.conf sean resueltos correctamente:
      ProxyPass / http://www.artpropensity.com:9080/VirtualHostBase/http/www.artpropensity.com:80/artpropensity/VirtualHostRoot/
    ProxyPassReverse / http://www.artpropensity.com:9080/VirtualHostBase/http/www.artpropensity.com:80/artpropensity/VirtualHostRoot/
    Usando "wget -sS ..." como línea de comando tampoco funciono para mí. Terminé corriendo un browser sobre un servidor externo usando X-windows. Setie el browser a no-cache (comprueba por nuevas páginas todo el tiempo) para asegurarme que este no cacheo items y en cambio hizo una petición total a Apache cada vez que este tuvo accedió al sitio. También usé su consejo y modifique:
    $ tail -f Z2.log
    para asegurarme de que Plone no estaba sirviendo arriba los .js, .css, .gif. etc y en cambio Apache estaba sirviendo estos arriba una ves cacheados. Yo note 304's sobre algunos ítems, pero asumí esto porque el navegador estaba seteado a no-cache y esto forzaba a Apache a chequear con Plone para ver si el archivo había cambiado.

    Noté un aumento de velocidad de 4 peticiones/seg. a un promedio de 300 utilizando Apache 2 caching.

Decidiendo que cachear

¿Qué contenido puede ser cacheado y como establecerlo para obtener una experiencia óptima?

Logeese a su sitio Zope como usuario con derechos de Manager y navegue a su Sitio Plone a través del ZMI. Click the HTTPCache y luego mire en la pestaña Associate. Notar que ningún ítem esta asociado actualmente con este.

Cuando asociamos ítems con el HTTPCache, usted no esta asociando content ítems, en cambios usted esta asociando las diferentes vistas disponibles. Esto significa que usted puede asegurarse que su template view esta siendo cacheada, pero edit templates no lo esta. Asegúrese que las opciones All para Locate Cacheable Objects, All para Of the type(s) y Search Subfolders están todas seleccionadas, click el botón Locate. Luego de algunos momentos, usted debería obtener una lista de todos los skin ítems en su sitio.

Preste mucha atención sobre los ítems que ha seleccionado de la lista. Usted puede seguramente cachear todas las imágenes, todos los archivos, todos los CSS y todos los Javascripts. Además, usted debería asegurarse que los templates de view para todos los content types disponibles están siendo cacheados. (Por ejemplo, newsitem_view para los News Items.) Este especialmente seguro de chequear que cualquier ítems que usted haya customizado dentro de una carpeta skin diferente haya sido además seleccionado.

Ahora usted debería tener una lista muy larga con ítems a ser cacheados, ahora solo clickee para guardar sus cambios.

IMPORTANTE: Si usted selecciona templates que están localizados en el sistema de archivos, la asociación con un cache manager no persistirá, por lo tanto esta se habrá ido la próxima ves que usted reinicie el servidor. Para crear una cache manager asociación persistente, usted debería utilizar archivos .metadata sobre el sistema de archivos. Por ejemplo, mire en cualquiera de los archivos en plone_images.

Asumiendo que usted ha hecho todo esto de manera correcta, debería poder ver ahora que apache esta comenzando a cachear sus páginas. Podemos comprobar esto usando wget y mostrando la salida de HTTP response:

  wget -sS --delete-after http://yoursite.com/

--03:28:46-- http://yoursite.com/
=> `index.html'
Resolving yoursite.com... done.
Connecting to yoursite.com[WWW.XXX.YYY.ZZZ]:80... connected.
HTTP request sent, awaiting response...
1 HTTP/1.1 200 OK
2 Date: Mon, 19 Jan 2004 03:28:46 GMT
3 Server: Zope/(unreleased version, python 2.3.2, linux2) ZServer/1.1 Plone/2.0-RC3
4 Vary: Accept-Encoding
5 Content-Length: 32125
6 Expires: Mon, 19 Jan 2004 04:28:43 GMT
7 Last-Modified: Mon, 19 Jan 2004 03:28:43 GMT
8 Cache-Control: max-age=3600
9 Content-Type: text/html;charset=utf-8
10 Age: 4
11 X-Cache: HIT from yoursite.com
12 Connection: close
Notar que ahora la cabecera X-Cache esta mostrando un cache HIT. Esto es exactamente el resultado que nosotros queremos. Ahora que Apache esta cacheando el resultado de sus paginas Plone, usted puede probar para ver que tipo de diferencias ha logrado esto. Una ves mas, usando la utilidad Apache Benchmark, nosotros podemos probar el sitio:
  /usr/sbin/ab -n 100 http://yoursite.com/

Benchmarking yoursite.com (be patient).....done
Server Software: Zope/(unreleased
Server Hostname: yoursite.com
Server Port: 80

Document Path: /
Document Length: 32125 bytes

Concurrency Level: 1
Time taken for tests: 0.116 seconds
Complete requests: 100
Failed requests: 0
Broken pipe errors: 0
Total transferred: 3252200 bytes
HTML transferred: 3212500 bytes
Requests per second: 862.07 [#/sec] (mean)
Time per request: 1.16 [ms] (mean)
Time per request: 1.16 [ms] (mean, across all concurrent requests)
Transfer rate: 28036.21 [Kbytes/sec] received
Note en particular el tiempo tomado para esta prueba: 0.116 segundos, o mucho mejor 0.0016 segundos por petición! Esto nos da alguna indicación de que tan rápido sera este sitio capaz de correr.

Usando Apache Benchmark para controlar 100 peticiones consecutivas es apenas un indicativo de la verdadera velocidad en la que su sitio esta corriendo, sin embargo. Para poner esta configuración en una prueba verdadera, trate usando el rasgo de coincidencias, que le permite controlar peticiones simultáneamente. En este ejemplo, ab controla 100000 peticiones con 100 peticiones coincidentes. Esto es el equivalente a un sitio a enterprise-level bajo media a pesada carga:
  /usr/sbin/ab -n 100000 -c 100 http://yoursite.com/

Benchmarking yoursite.com (be patient)
Server Software: Zope/(unreleased
Server Hostname: poked.org
Server Port: 80

Document Path: /
Document Length: 32125 bytes

Concurrency Level: 100
Time taken for tests: 115.732 seconds
Complete requests: 100000
Failed requests: 0
Broken pipe errors: 0
Total transferred: -1041856680 bytes
HTML transferred: -1081567796 bytes
Requests per second: 864.07 [#/sec] (mean)
Time per request: 115.73 [ms] (mean)
Time per request: 1.16 [ms] (mean, across all concurrent requests)
Transfer rate: -9002.32 [Kbytes/sec] received
Estos resultados muestran que la combinación de Apache y Zope es capaz de servir 100000 solicitudes poe debajo de los 2 minutos. Vale la pena recordar otra vez que esto está sobre una 1.8GHz Intel Celeron con sólo 128MB de RAM, corriendo un sistema básico de Redhat 7.3, que es muy lento para un servidor de producción. Sobre un servidor típico Intel Dual Xeon 2.4GHz con 1GB de RAM, espere un aumento de velocidad de más del 100%.

Vale la pena indicar que hay limitaciones sobre este intento de cacheado. En el ajuste de la cabecera Last-Modified al tiempo en que la página fue dada y el ajuste de la max-age a 3600 segundos, hace que todo el contenido del sitio tenga un tiempo de vida de 1 hora. Esto quiere decir que en el peor de los casos, una actualización del sitio podría tomar una hora para aparecer. Esto puede ser resuelto forzando una anulación del cacheado para una página en particular, que puede ser hecho simplemente CTRL-refeshing la página en la mayor parte de los navegadores.

Otra limitación es que, si usted usa su nombre de dominio principal para logearse y editar su sitio de Plone, usted puede experimentar algún comportamiento extraño en los navegadores que no respetan correctamente las cabeceras de caching (como Internet Explorer). Un modo fácil de trabajar alrededor de esto es añadir un nuevo subdominio para los usuarios que están editando su sitio, como cms.yoursite.com. Entonces, en su archivo de configuración de Apache, simplemente añada una nueva sección VirtualHost para su CMS de vista, sin cualquiera de las directivas de caching:
  <VirtualHost *>
ServerName cms.yoursite.com
ServerAdmin webmaster@yoursite.com
ProxyPass / http://cms.yoursite.com:8080/VirtualHostBase/http/cms.yoursite.com:80/yourplonesite/VirtualHostRoot/
ProxyPassReverse / http://cms.yoursite.com:8080/VirtualHostBase/http/cms.yoursite.com:80/yourplonesite/VirtualHostRoot/
</VirtualHost>
Así, cualquiera que tenga que editar el sitio evitará el caching completamente.

Copyright (C) 2004-2007 Menttes - All Rights Reserved