Todos sabemos que en servidores de alta concurrencia el tema del tráfico es crítico. Reducir la cantidad de requests (pedidos) HTTP que hacen los clientes de un sitio muy visitado resulta clave para optimizar el rendimiento de nuestro servidor. Cada pedido implica una cantidad de ancho de banda que se consume (el pedido que va y la respuesta que vuelve) y procesamiento del lado del servidor y del cliente. Si logramos reducir la cantidad de los requests vamos a estar aliviando tanto el ancho de banda como la carga del servidor, con lo cual, vamos a poder atender a mayor cantidad de clientes con los mismos recursos.
Hay muchos aspectos en el diseño de la arquitectura de una aplicación que deben ser tenidos en cuenta para reducir la cantidad de requests. No podemos cubrir todos aquí, pero uno fundamental es el cache. El cache es, por lo general, una reproducción estática de un conjunto de información dinámica. Es decir, un almacenamiento temporal de una información que puede cambiar, durante un período de tiempo en el que se supone que no ha de hacerlo.
Por ejemplo, si yo tengo un conjunto grande de datos sobre los ingresos de los miembros de una familia y debo mostrar informes realizados sobre esos datos, tendría que hacer toda una serie de cálculos que mes a mes irían dando resultados distintos. Si yo sé que a lo largo de un mes, los datos de orígen no van a cambiar, puedo hacer un cache (una copia de los resultados ya calculados) para mostrarlos durante todo ese mes y no volver a hacer los cálculos.
Hay varios tipos de cache, que se pueden implementar en distintos segmentos de la arquitectura de una aplicación. En este caso nos ocuparemos del cache que se hace en el cliente HTTP (el browser) para evitar hacer consultas innecesarias al servidor (el Apache), con los beneficios que mencionamos más arriba.
Cuando cualquiera de nosotros visita un sitio web con un browser común, éste último se ocupa de hacer un request HTTP al servidor pidiendo el contenido de la URL que solicitamos (por ejemplo, el contenido del archivo http://www.tail-f.com.ar/index.php). Ahora bien, cuando recibe el contenido del archivo, si es HTML, es muy probable que éste incluya referencias a toda otra serie de archivos (imágenes, archivos de CSS, archivos de JavaScript, etc.). Automáticamente, y en forma totalmente transparente para nosotros, el browser va a hacer los requests de esos archivos, para bajar las imágenes y archivos que necesite para mostrarnos la página web a la que nosotros queremos acceder. Pero ¿qué sucede?, muchos de estos archivos, especialmente las imágenes, lo más probable es que no cambien casi nunca. El logo de la empresa dueña del sitio seguirá siendo el mismo y si yo actualizo la página o voy de la home a la sección de contacto, el logo que aparece en el encabezado se estaría descargando muchas veces. La gente que definió el protocolo HTTP ya tenía en mente este tipo de situaciones, entonces definió una serie de directivas que se envían en los headers de los mensajes HTTP, a través de las cuales el servidor le puede indicar al cliente si debe guardar ese archivo y por cuánto tiempo. De esta manera, al visitar la home del sitio por primera vez, el servidor puede decirme “este logo va a permanecer igual por todo un mes, así que guardalo y no me lo vuelvas a pedir hasta entonces”, y si yo soy obediente, lo haré, y nos haré un favor a los dos. Porque la próxima vez que vea que un HTML de este sitio me indica que tengo que poner la imagen logo.jpg en algún lado, la buscaré en mi disco rígido en vez de pedírsela al servidor, pudiendo mostrarla mucho más rápido al visitante.
¿Cómo se configura esto en Apache?
Hay dos módulos de Apache que nos servirán en este punto:
El primero permite manipular los headers (cabeceras) de los requests y responses que envía Apache. El segundo sirve para control uno de esos headers en particular, que es justamente el llamado “Expires”, que define el tiempo de expiración del archivo que se está mandando en un response.
Por lo tanto, aplicando unas reglas con expresiones regulares y estos dos módulos, en el httpd.conf de Apache o en un .htaccess, podemos definir cómo será el tratamiento de distintos tipos de archivos.
Por una cuestión de simplicidad yo lo he probado con un .htaccess, pero usarlo en el httpd.conf resultaría más óptimo aún, porque el procesamiento del .htaccess de por sí le quita rendimiento a Apache.
A continuación, dejo un ejemplo de configuración de un .htaccess en el cual se define que los archivos multimedia (sonido y video) deberán ser cacheados por un año, las imágenes por una semana, los archivos estáticos más comunes (html, css, js) cada 2 horas y los archivos dinámicos (php, cgi, pl) no deberán tener cache.
# Turn on Expires and set default to 0 ExpiresActive On ExpiresDefault A0 # Set up caching on media files for 1 year (forever?) <FilesMatch "\.(flv|ico|pdf|avi|mov|ppt|doc|mp3|wmv|wav)$"> ExpiresDefault A29030400 Header append Cache-Control "public" </FilesMatch> # Set up caching on media files for 1 week <FilesMatch "\.(gif|jpg|jpeg|png|swf)$"> ExpiresDefault A604800 Header append Cache-Control "public" </FilesMatch> # Set up 2 Hour caching on commonly updated files <FilesMatch "\.(xml|txt|html|js|css)$"> ExpiresDefault A7200 Header append Cache-Control "proxy-revalidate" </FilesMatch> # Force no caching for dynamic files <FilesMatch "\.(php|cgi|pl|htm)$"> ExpiresActive Off Header set Cache-Control "private, no-cache, no-store, proxy-revalidate, no-transform" Header set Pragma "no-cache" </FilesMatch>
Fuente del código: AskApache.com

Como veo que entiendes del tema te queria preguntar.
Las caches de paginas php para servirlas como estáticas (hay un plugin WP que lo hace) parece muy útil, pero a mí me ha dado un problema; parece que en el momento de generar las cachés (muchas paginas) se disparan las conexiones sql y muchas veces acaba con colgarse el server. Es un sitio con muchas visitas. No sabrás a que puede deberse…
Habría que ver el plugin. Yo estoy usando WP-Cache. Es plugin básicamente lo que hace es guardar una copia estática por un tiempo x (que se define en la configuración) de las páginas que genera WordPress, por ejemplo, las de cada post. Entonces supuestamente a partir de la segunda vez que se intenta ingresar a la misma página, en vez de generarse el contenido nuevamente haciendo las consultas SQL, se sirve el archivo estático.
Habría que revisar tu caso particular para ver cuál es el problema. Es sabido que WordPress de por sí no tiene muy buenas queries y no funciona bien bajo mucha demanda, por eso el cache es tan útil. Pero si cuando la gente entra a tu sitio se están haciendo las consultas SQL es porque el cache no está andando. Te diría que en primer lugar revises eso.
Por otro lado, también habría que hacer una auditoría para ver qué consultas son las más pesadas que se están generando y, en todo caso, optimizarlas.
Saludos
Muy buen tip, siempre viene bien tenerlo a mano. Solo una salvedad, en la Expresión Regular definida para deshabilitar el cache a páginas dinámicas se incluye la extensión “htm”, que debería ir en el apartado anterior, el de 2 horas de cache.
Desde que conocí el blog no me pierdo una nota, un saludo.
@Adrian: la verdad cuando lo ví en el código original de AskApache pensé lo mismo. La extensión “.htm” (que revisando un poco en Internet me enteré que la legamos de cuando la gente empezó a usar productos de M$ que solamente permitían extensiones de 3 letras) y la “.html” por lo general son lo mismo, así que bien podrían tener un cache por dos horas. De hecho, siendo contenido estático, podría tener cache de un día o una semana.
Gracias por el comentario!
Interesting article, i have bookmarked your blog for future referrence, thanks
I’m glad it helped.
Muy bueno una vez más tu articulo sobre apache.
Saludos Nikitux
@Nikitux gracias, me alegro que te haya gustado
Funcionando de forma extraordinaria.
Y que opina de esta otro forma cual es mejor..?
Espero comentarios..?
# BEGIN Compress text files
SetOutputFilter DEFLATE
# END Compress text files
# BEGIN Expire headers
ExpiresActive On
ExpiresDefault “access plus 1 seconds”
ExpiresByType image/x-icon “access plus 2592000 seconds”
ExpiresByType image/jpeg “access plus 2592000 seconds”
ExpiresByType image/png “access plus 2592000 seconds”
ExpiresByType image/gif “access plus 2592000 seconds”
ExpiresByType application/x-shockwave-flash “access plus 2592000 seconds”
ExpiresByType text/css “access plus 604800 seconds”
ExpiresByType text/javascript “access plus 216000 seconds”
ExpiresByType application/x-javascript “access plus 216000 seconds”
ExpiresByType text/html “access plus 600 seconds”
ExpiresByType application/xhtml+xml “access plus 600 seconds”
# END Expire headers
# BEGIN Cache-Control Headers
Header set Cache-Control “max-age=2592000, public”
Header set Cache-Control “max-age=604800, public”
Header set Cache-Control “max-age=216000, private”
Header set Cache-Control “max-age=600, private, must-revalidate”
# END Cache-Control Headers
# BEGIN Turn ETags Off
Header unset ETag
FileETag None
# END Turn ETags Off
# BEGIN Remove Last-Modified Header
Header unset Last-Modified
# END Remove Last-Modified Header
El filtro del formulario quito codigo aca le dejo el link de donde lo saque y esta completo
http://www.taringa.net/comunidades/wordpress/2593/Compimi-tus-archivos-y-aplica-cache-para-ganar-en-performanc.html
Saludos y pero su comentario de cual es mejor..?
Ambos son similares. Habría que probar el que ud. dice. La principal diferencia que veo es que el expires lo aplica por mime type en vez de por extensión del archivo. Lo cual puede ser bueno o malo dependiendo de la aplicación (si uno genera dinámicamente imágenes en un archivo .php, esta alternativa puede ser útil o molesta dependiendo si uno quiere cachear eso o no).