De LAMP a LEMP

Ud. probablemente ya sabe lo que es LAMP (Linux Apache MySQL PHP) el stack sobre el que corren los más populares CMS Open Source como Drupal, Joomla o WordPress, pero probablemente aún no haya escuchado de LEMP (Linux Nginx MySQL PHP), ya que incluso en Wikipedia el término aún no está definido. La diferencia es pues el servidor web. La idea detras de LEMP es muy simple reemplazar el muy flexible y casi omnipresente servidor Apache por el más liviano y ágil Nginx. Si esa fuera la única diferencia, pues no valdría la pena el cambio. Pero que pensaría si le dijera que hacer ese cambio puede transformar radicalmente la performance de su página web y permitir que por ejemplo con un pequeño VPS se pueda atender decenas de miles de visitas diarias. Pues bien en este post les contaré la historia destras de la migración de LAMP a LEMP y como este blog pudo reducir increíblemente su tiempo de carga.

Durante mucho tiempo la escalabilidad del blog era un problema que me tenía preocupado, siempre temía que por alguna razón un post llegara a ser popular y miles de visitantes saturen el server y lo traingan al piso. Algo que no ha pasado, pero que muchos calificarían como un problema que les gustaría tener. Por ello durante estos últimos años ensayé varias posibles soluciones, evalué moverlo a Blogger (pero era muy limitado, igual en los picos Blogger te limitaba el tráfico), probé con la optimización del Apache, del MySQL, instalé el eAccelerator para compilar-cachear los scripts de PHP, hice pruebas de varios plugins de cacheo para WordPress y finalmente me quedé con W3 Total Cache y lógicamente cada mejora implicaba hacer benchmarking del site con las herramientas que describí en el post "Midiendo la performance de un website". Sin embargo nada de eso parecía resolver el problema de que si más visitantes llegaban era necesario disponer de más RAM y más CPU. Es decir la escalabilidad se conseguía sólo a través de poner más hardware (en el caso de los VPS hacer un pago extra para poder acceder a más recursos). Pero desde el 2009 el nombre Nginx ya era comentado entre la cofradía de sysadmin y muchos ISP lo usaban para hostear websites, pero tenía un pequeño incoveniente, sólo soportaba PHP a través de FastCGI y usar PHP de esta manera requería de spawn-fcgi y lamentablemente existía un problema de confiabilidad (se caía muy frecuentemente).

El problema de spawn-fcgi era tan serio que Andrei Nigmatulin creo PHP-FPM como un parche al código de PHP para permitirle operar de manera confiable sin tener que depender de spawn-fcgi. Lo cual era una solución pero requería parchar el código de PHP, esto era desde mi punto de vista poco confiable porque no tenía la certeza de que el proyecto podría tener larga vida, especialmente luego de que su creador declarara públicamente que no podía darle soporte por más tiempo. Pero desde noviembre del año pasado el código de PHP-FPM pasó a formar parte del core de PHP, con lo cual ya se podía usar de manera confiable en producción porque la continuidad estaba garantizada por la propia continuidad de PHP.

Finalmente animado por todos los buenos comentarios de Nginx y de PHP-FPM, decidí probarlos. Debo decir que no me ha decepcionado, el uso de CPU y RAM fue casi plano independientemente de la carga que se le ponga al server, pero el sólo hecho de reemplazar LAMP con LEMP no mejora la velocidad con la que se muestran las páginas de WordPress. Después de todo tenía mi LAMP optimizado para mi WordPress y lo estaba comparado contra un LEMP de paquete. Así que era necesario nivelar el piso a través de la optimización de LEMP.

La primera y obvia mejora era usar un compilador-cache para PHP, había usado eAccelerator en LAMP y me ha funcionado bien, pero en todas las páginas que encontré todas mencionaban a APC (las dos razones más citadas son que es parte de los repositorios PEAR y que Facebook lo usa), así que decidí seguir a la mayoría e instale APC. La compilación y cacheo de los scripts definitivamente mejoró la velocidad de rederizado de las páginas pero aún se podía optmizar un poco más. Así que instalé memcache (para reducir el número de queries a MySQL) y habilité el soporte de memcache en WordPress, lo cuál le dio un boost adicional a la carga de las páginas.

Pero moviendome de tutorial en tutorial encontré a Varnish, un proxy inverso que hace cacheo de contenido estático, es decir guarda en disco/memoria las páginas generadas dinámicamente por WordPress para no tener que volver a ejecutar un script si la página ya está cacheada y eso fue la cereza sobre el pastel, no solamente las páginas cargaban más rápido sino que el uso de CPU y memoria se fueron al piso. Como resultado reduje la RAM del VPS de 1GB a 512MB con el ahorro que se deriva de ello, pero me he dado cuenta de que incluso con 256MB el VPS va bien. Pero de momento no tomaré riesgos y veré que tal va durante el próximo mes con 512MB, si veo que no hay picos y todo opera normalmente bajaré la memoria a 256MB.

Si deseran hacer lo mismo les recomiendo este howto de CryptkCoding que sintetiza varios otros que he visto en la red y funciona para Ubuntu, aunque con pequeños cambios tambien es útil para Debian. Si es que me doy un tiempo preparé uno en español específicamente para Debian y lo publicaré en la sección de Tutoriales y Howtos.

Como prueba de los increíblemente lineal de la mezcla LEMP + APC + memcache + Varnish, aquí les dejo una gráfica de Load Impact de un stress test a este blog y como el tiempo de carga es independiente del número de clientes conectados concurrentemente:

Load Impact

Aquí el resultado de una prueba con Apache Benchmarking (ab) desde otro server en el mismo switch (10,000 solicitudes con 100 clientes concurrentes), el benchmarking arroja la sorprendente velocidad de casi 3000 solicitudes por segundo:

~# ab -n 10000 -c 100 http://www.volkanrivera.com/esp/
This is ApacheBench, Version 2.3 <$Revision: 655654 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/
 
Benchmarking www.volkanrivera.com (be patient)
Completed 1000 requests
Completed 2000 requests
Completed 3000 requests
Completed 4000 requests
Completed 5000 requests
Completed 6000 requests
Completed 7000 requests
Completed 8000 requests
Completed 9000 requests
Completed 10000 requests
Finished 10000 requests
 
 
Server Software:        nginx/1.0.6
Server Hostname:        www.volkanrivera.com
Server Port:            80
 
Document Path:          /esp/
Document Length:        60689 bytes
 
Concurrency Level:      100
Time taken for tests:   3.403 seconds
Complete requests:      10000
Failed requests:        0
Write errors:           0
Total transferred:      611319358 bytes
HTML transferred:       606948931 bytes
Requests per second:    2938.72 [#/sec] (mean)
Time per request:       34.028 [ms] (mean)
Time per request:       0.340 [ms] (mean, across all concurrent requests)
Transfer rate:          175439.26 [Kbytes/sec] received
 
Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0   21 246.4      1    3000
Processing:     2    6  18.6      3     398
Waiting:        0    3  16.6      1     397
Total:          2   27 248.2      4    3218
 
Percentage of the requests served within a certain time (ms)
  50%      4
  66%      4
  75%      5
  80%      5
  90%      6
  95%     21
  98%     33
  99%    209
 100%   3218 (longest request)
 
PS: Un detalle que olvide mencionar es que aún sigo usando el plugin W3 Total Cache. Y que he retirado todos los bookmarks sociales a excepción del botón "Me gusta" de Facebook de la página de inicio del blog, eso redujo grandemente el tiempo de renderizado también.

3 comentarios en “De LAMP a LEMP

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.