El servidor HTTP de Apache no es más lento que nginx

En los últimos meses, según las estadísticas de Netcraft, nginx se habría puesto por encima de Apache HTTPd en servidores frontales HTTP. La popularidad de nginx es un hecho, si bien el mérito que tiene no lo sea tanto. Y no porque recientemente algunos medios se hayan hecho eco de que allanaron la sede de la empresa que mantiene nginx y que imputaron a uno de sus cofundadores por una reclamación de derechos de autor por parte de Rambler porque estaba trabajando en esa empresa mientras desarrollaba este software, sino por cómo consiguió nginx esta popularidad.

Si nos remontamos a los años previos a la existencia de Apache HTTPd 2.4, con gran dominio en el mercado, no estaba tan extendida la tecnología multinúcleo y multihilo. También era muy habitual encontrar la pila tecnológica LAMP, en el que Apache HTTPd y PHP estaban juntos mediante un módulo para Apache HTTPd llamado mod_php. Cuando llegó nginx no tenía un módulo similar para PHP, sino que se utilizaba la interfaz FastCGI para cargarlo. Para entonces había aparecido php-fpm, donde FPM significa gestor de procesos FastCGI, y esta combinación obtenía un rendimiento notablemente superior en servidores multinúcleo y multihilo, consiguiendo mejor rendimiento. A su vez, el consumo de memoria en general de combinar nginx y php-fpm daba muchos mejores resultados.

Para ambientes en los que no se requería PHP y se servían ficheros de forma estática, nginx también rendía mejor que Apache HTTPd con hardware que no era multiproceso. Pero con Apache HTTPd 2.4 y la aparición del módulo multiproceso (MPM) llamado event de forma recomendada, como alternativa a otros módulos multiproceso de Apache HTTPd como el tradicional prefork y el worker, podía tener un desempeño similar. Eso sí, nginx viene configurado de serie orientado de cierta forma para pruebas de rendimiento (benchmarks), mientras que Apache HTTPd viene por lo general configurado para resultar más cómodo para trabajo multipropósito.

Por tanto, dos de los motivos por los que Apache HTTPd parece que todavía rinda menos es porque las pruebas de rendimiento no están en igualdad de condiciones. En muchos casos no se está utilizando el módulo multiproceso adecuado o se está utilizando mod_php en lugar de php-fpm, o php-fpm está configurado usando puerto TCP en lugar de sockets UNIX. Otro caso típico es no desactivar la opción AllowOverride All de Apache HTTPd, que sirve para comprobar la existencia de ficheros .htaccess de forma recursiva para cada petición, causando una caída de rendimiento, mientras que nginx no soporta del todo algo parecido como .htaccess y por eso aquí toma ventaja sin tocar la parte de PHP. Otros casos puede ser cómo esté configurado KeepAlive, si tiene HTTP/2 habilitado o si se han desactivado módulos de Apache HTTPd que no son necesarios, ya que muchas distribuciones tienen habilitados módulos no necesarios de forma predeterminada e incrementan el consumo de memoria de los procesos en ejecución, entre otras configuraciones ya más específicas.

Dicho esto, si se configuran ambos servidores HTTP de forma adecuada para una carga de trabajo en particular, Apache HTTPd puede igualar o incluso superar a nginx en rendimiento, sin embargo hay muchas guías, en muchos casos obsoletas, incompletas o imparciales que no están comparando de forma adecuada ambos servidores.

Apache HTTPd gana en características e innovación a nginx

No solamente por la cantidad de módulos disponibles para Apache HTTPd en muchas distribuciones y que no tienen equivalente nginx, sino que todavía hay muchas características de nginx que para incorporarlas hay que compilarlas manualmente, algo que no facilita nada la tarea de instalar actualizaciones en caso de vulnerabilidades. También tardan más en agregar características importantes, como es el caso del soporte de HTTP/2.

Una de las características notables de HTTP/2 es el soporte de PUSH por parte del servidor, permitiendo enviar ficheros al cliente antes de que los pida, permitiendo acelerar los tiempos de carga, especialmente en conexiones con mayor latencia de forma notable al ahorrar un ciclo de consulta. Esta característica estaba implementada en httpd 2.4.18, publicado a finales de 2015. En el mismo año, nginx alegaba que su versión de pago (la versión “plus”) que soportaba por completo HTTP/2. Irónicamente, en la misma nota indicaban que todavía no soportaba PUSH, a pesar de que está definido en el mismo documento RFC que define HTTP/2, por lo tanto el titular era engañoso. Esta característica no se agregó finalmente a nginx hasta febrero de 2018 (y en la “plus” en abril), al menos 2 años y 3 meses (2 años y 5 meses la “plus”) después de que lo tuviera disponible Apache HTTPd.

Otro problema que tiene nginx es con el manejo de los certificados para usar con HTTPS si estos tuvieran la opción must-staple. Los certificados generados con esta característica, en los navegadores que lo soporten, exigirán que el servidor ofrezca la información de revocación OCSP “grapada” en la negociación de la conexión segura y que no la obtengan los navegadores por su propia cuenta. La ventaja del grapado OCSP se explicó en una entrada de blog anterior, por motivos de velocidad y privacidad. Además, si todos los clientes soportaran must-staple como es debido, permitirían hacer realmente útil en la práctica a OCSP. Si un navegador que soporta y respeta must-staple, como es el caso de Firefox, trata de cargar una página servida con nginx por primera vez, nginx la enviará sin grapado, haciendo que la página no cargue y aparezca un error de seguridad, algo que se podría considerar intolerable. Apache HTTPd pausa la conexión hasta que obtiene el estado de revocación si no lo tiene cacheado, mientras que nginx no lo tiene implementado a fecha de hoy. Quizás no tenga prioridad porque quizás afecte a las pruebas de rendimiento en frío. En cualquiera de los dos casos, estos servidores deberían implementar una precarga del estado OCSP sin existir una carga inicial para un desempeño ideal en frío (a principios de 2019 ninguno de los dos lo hacía), pero por lo menos en el caso de Apache HTTPd no falla como hace nginx.

Como conclusión, no tiene sentido elegir nginx solamente porque aparenta ser más rápido. Lo indicado en este artículo tiene el objetivo de dar a conocer algunos puntos que no suelen conocerse hasta que te encuentras con ellos.

Recomendaciones para configurar el servidor HTTP de Apache

Para finalizar, algunas recomendaciones cuando se instala Apache HTTPd, adicional a las recomendaciones en artículos anteriores como el grapado OCSP y PUSH de servidor:

  • Deshabilitar módulos que no son necesarios para ahorrar memoria y tiempos de carga.
  • Configurar AllowOverride como “none” para desactivar .htaccess y cargar la configuración estática desde ficheros .conf si fuera posible.
  • No usar mod_php, usar php-fpm con sockets UNIX en un SetHandler y este en un FilesMatch solo para ficheros .php, usando mod_proxy_fcgi para FastCGI.
  • Usar el mpm event, es el único que soporta HTTP/2.
  • Habilitar HTTP/2 mediante el módulo mod_h2.

Deja un comentario

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