Optimizar [un huevo] el Apache
Con el menéame me dí cuenta de dos cosas:
Las cantidad de cosas que se pueden hacer un “viejo” Xeon Dual haciendo que el código y los SQL sean muy eficientes (más de 2.000.000 de ejecución de scripts/páginas PHP diariamente y una media de 200 consultas por segundo –con picos de varias veces esa cantidad).
Que los parámetros por defecto del Apache no están para nada ajustados a servidores con mucha carga. Especialmente uno…
Todos más o menos saben que hay que ajustar el número de procesos máximos, el mínimo y los procesos “en espera” para atender a nuevas peticiones. En el menéame está de la siguiente forma:
StartServers 40 MinSpareServers 30 MaxSpareServers 50 MaxClients 240 MaxRequestsPerChild 10000 #Para liberar la memoria consumida por algunos scripts "gordos"
También es importante reducir el timeout:
Timeout 30
Y por supuesto, minimizar el número de módulos cargados ya que cada uno de ellos consume memoria.
Pero si hay un parámetro que es fundamental para reducir el número total de procesos (y por lo tanto consumo de memoria) para no llegar a los límites es algo que muy poca gente lo hace. Reducir el tiempo de espera para las conexiones persistentes. Por defecto es de 15 segundos, pero resulta que no tiene sentido tanto tiempo. Cuando un navegador usa las conexiones persistentes es para bajar las imágenes una tras otra, en serie y lo más rápido posible. Así que no tiene sentido “gastar” un proceso para que quede consumiendo memoria y sin hacer nada durante 15 segundos.
En menéame cambié de 15 a 3 segundos:
KeepAliveTimeout 3
Y fue impresionante, el número medio de procesos Apache bajó de 160-180 a no más de 120 (en general no supera 100). Ahora mismo estamos en hora que no es pico pero está entre las más altas, y no supera 90 procesos:
$ ps ax | grep apache | wc -l
90
Hace tiempo leí que apache 1.x funcionaba mejor con php que no apache 2, ¿sabes si esto ya está resuelto o era una leyenda urbana? Por cierto, ¿qué tipo de MPM usas en Meneame?
Comment by Arnau — Tuesday 26/9/2006 @ 16:16
Ricardo, ¿habría alguna ventaja en pasar a usar FastCGI (y así dejar el prefork para trabajar con mod_php) y usar el trabajo con hilos de Apache2?
No sé si es una pregunta complicada o no.
Comment by Juanjo — Tuesday 26/9/2006 @ 16:17
Al #1: Arnau, el PHP con prefork funciona perfectamente en Apache2 (lo usamos en el menéame).
Al #2: No lo creo Juanjo, un módulo debería ir bastante mejor que un fastcgi (que no sé cómo va en PHP), y además poniendo los parámetros adecuados del mínimo y máximos de procesos en espera se consiguen muy buenos resultados.
Comment by gallir — Tuesday 26/9/2006 @ 16:19
Gracias por comentar tus “truquitos” para optimizar un servidor Web Apache.
La verdad es que es muy fácil instalar un apache y hacer una aplicación con php, pero cuando lo empiezas a usar en serio, te empiezas a hacer preguntas de cómo podrá la gente dar tanto servicio con una máquina más pequeña si a mi con esta no me llega ni para empezar?!!!
Ahora que hablas de optimizar… yo tengo una duda/curiosidad con las consultas SQL del menéame… ¿por qué no usas consultas parametrizadas?
Yo siempre las uso para impedir SQL Injection y supuestamente porque son más rápidas…
Aunque no conozco ninguna aplicación php que las use (no uso PHP, estoy estancado con Perl ;), pero en Perl y en ASP o .NET si que existen y son usadas.
Comment by DN — Tuesday 26/9/2006 @ 17:03
> Ahora que hablas de optimizar… yo tengo una duda/curiosidad con las consultas SQL del menéame… ¿por qué no usas consultas parametrizadas?
No se podía, hasta el mysql 4.1 y las nuevas funciones PHP/PDO (o mysqli, http://es.php.net/mysqli)
Comment by gallir — Tuesday 26/9/2006 @ 17:53
Hola Ricardo, una pequeña pregunta ¿hay alguna fórmula para calcular la memoria necesaria respecto a conexiónes / segundo ? tengo oido que por cada conexión hay que calcular unos 2 Kbytes de memoria.
¿que cálculo usas tu?
Un saludo y felicidades por menéame.
Comment by Xavis — Tuesday 26/9/2006 @ 17:54
Ya que estamos con menéame internals, ¿empleas la query caché de MySQL en algunas queries?
Imagino que en todas no tendrá sentido, pero puede que para algunas sí… como las de la portada (siempre que tengáis memoria en el servidor para dedicar a ese caché).
Comment by Juanjo — Tuesday 26/9/2006 @ 17:55
Al #6, no lo sé Xavis, pero lo que más consume memoria es cada proceso de apache, así que lo del TCP/IP es despreciable. La cantidad que consume cada proceso depende de muchos factores, como módulos y el “malloc” que haga cada uno para ejecución. LO que te puedo decir es que en el menéame, con hasta 200 procesos apache y otros 200 hilos de mysql, y con 160 MB de ram para caches del mysql, no llegamos nunca a los 500 MB.
Al ~7: Juanjo, sí, por defecto está habilitada y especificamos SQL_NO_CACHE en algunas pocas (lo puedes ver en el código) que se hacen sobre todo para verificar la IP de cada conexión.
Estos son los parámetros principales del mysql.
thread_stack = 128K
key_buffer = 150M
max_allowed_packet = 1M
table_cache = 256
sort_buffer_size = 2M
read_buffer_size = 2M
read_rnd_buffer_size = 8M
myisam_sort_buffer_size = 64M
thread_cache_size = 8
thread_concurrency = 4
query_cache_size = 16M
query_cache_type = 1
Comment by gallir — Tuesday 26/9/2006 @ 18:07
Optimizar [un huevo] el Apache
Ricardo Galli comparte algunas de las _enseñanzas_ que ha aprendido al estar día tras día ajustando el Menéame. En este post habla de cómo optimizar los parámetros del Apache en un servidor con mucho tráfico (más de 2.000.000 de ejecución de scripts/pá…
Trackback by meneame.net — Tuesday 26/9/2006 @ 21:45
Meneado
Comment by Habladorcito — Tuesday 26/9/2006 @ 21:50
#10, ya lo he visto, ya lo he visto
Comment by gallir — Tuesday 26/9/2006 @ 22:17
Muy bueno el post y mejores los comentarios…
Comment by nexus7 — Wednesday 27/9/2006 @ 13:06
Supongo que tambien usarás algún optimizador de código php. Yo me lo planteé cuando las visitas empezaron a aumentar. Un PIII no da para mucho. Y menos si utilizas wordpress, bastante pésimo de momento en su relación con mysql.
Ahora mismo utilizo turck-mmcache (http://turck-mmcache.sourceforge.net/index_old.html) porque lo encontre casi por causalidad en Debian. Sólo funciona para php4 porque es muy antiguo. Si no leí mal es del tío que ha hecho un optimizador de pago para zend.
Como de momento funciona bien no he actualizado a su sucesor, eacceleartor (http://eaccelerator.net/). eaccelerator es el heredero y nace debido al abandono del anterior proyecto. Este si soporta php5. Estan en reescribir parte del código debido a algún problema con la licencia (http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=280864).
Ciertamente se nota el cambio. La carga del ordenador se reduce y se estabiliza. Desaparecen muchos picos.
Comment by kike — Wednesday 27/9/2006 @ 13:38
En el menéame usamos el eaccelerator, y funciona muy bien.
No ganamos demasiado con las páginas índices porque la relación “compilación versus consultas” es baja, pero con las de historias individuales se multiplica por 5 o 6 como mínimo.
Comment by gallir — Wednesday 27/9/2006 @ 13:47
query_cache_size = 16M
¿Tienes un Dual Xeon y solo usas 16 MB de cache? Me parece muy poco.
Yo te recomiendo poner el KeepAlive off, funciona bastante mejor y consumes muchas menos conexiones.
Lo de reducir el timeout va muy bien para prevenir ataques DDoS.
Yo uso el eAccelerator para el PHP y aligera notablemente la CPU. Yo tenía un foro con 400.000 mensajes en un Celeron con 150 consultas por segundo de media y funcionaba correctamente.
Saludos,
Alex.
Comment by alex — Wednesday 27/9/2006 @ 18:06
Al #15, no hace falta más de eso, el hit ratio es elevado.
Lo del keepalive off no estoy convencido, por cada imagen que se baje se necesita un proceso de apache nuevo.
Comment by gallir — Wednesday 27/9/2006 @ 18:26
[Ricardo] bueno… no te voy a contar nada que no sepas.. pero puede ayudar a otros:
Yo además de toquetear la configuración del apache… tambien le he instalado el acelerador APC… y con él si que he notado una mejora bastante grande de rendimiento.
Aparte, claro, he activado la query cache de mysql.
Comment by Javi Moya — Wednesday 27/9/2006 @ 22:44