domingo, 12 de agosto de 2018

Updating hacía Debian 9.5.0 y MPM_Event en servidores Apache

Podéis preguntarle a mi pareja si queréis los niveles de obsesión que me trae Debian y GNU/Linux en general. No sería la primera vez que llegamos tarde a una cena porque me he quedado justamente antes de salir instalando de 0 máquinas en Debian con particiones cifradas, aplicando estrategias de seguridad por oscuridad y tratando de fortificar el servidor aumentando la disponibilidad. Recuerdo que una vez ella estaba duchada, vestida y pintada y yo aún sin duchar ni vestir porque estaba realizando la tercera instalación en ese día de un Debian o un CentOS Minimal para pruebas.

Así pues, tenía ganas de testear Debian 9, ya que aún no lo había testeado y quería ver qué cambios se habían aplicado con respecto a Debian 8 y probar el servidor Apache instalado, en qué módulo estaba y demás cuestiones que iba a ir descubriendo poco a poco. Así que decidí aprovechar uno de los fin de semana que iba a Córdoba para quedarme allí probando y testeando Debian 9 y es de lo que os vengo a hablar hoy.


Debian 9.5 trae importantes cambios, Bugfixes y security updates tal y como podemos ver en la release note de la web de Debian. Además incorpora software como, por ejemplo el famoso apt usado por gran parte de linuxeros, pero además incorporando mecanismos de seguridad para que APT rechace las sumas de comprobación débiles como SHA1. En el siguiente cuadro se dejan los package de Debian 8 Jessie frente a los paquetes de Debian 9 Stretch.



A nivel Kernel nos encontramos con Linux 4.9 LTS y en cuanto a software, destacar que se utiliza MariaDB 10.1 en lugar de MySQL by default, con las importantes mejoras que trae con ella. También hablar, por supuesto y como no podía faltar, del uso de PHP 7 en lugar de 5. Ya conocemos un poco las nuevas características de PHP 7 y además ya os puse en el post sobre Hardening de servidores en GLAMP la mejora de rendimiento de PHP 7 frente a PHP 5.


PHP 7 trae muchaas mejoras con respecto a PHP 5, en este artículo se mencionan 10, entre los que está el mejor aprovechamiento de la memoría, el control de los Fatal Errors o el uso de EngineExceptions para comprobar si algo existe o no.

Sobre las mejorías de Debian 9.5 me puedo tirar hasta mañana, pero me saldría un post excesivamente largo, por lo que comentar también que Debian 9.5 viene con Apache 2.4 con los cambios que implica esto y que comentaré después.



Aquí es donde estuve a punto de tirarme de los pelos. Entré en /etc/apache2/mods-enabled y vi mpm_event y yo quería llorar ya que yo soy era de Prefork y Event no lo había tocado ni usado nunca, pero bueno, vi que era una oportunidad de ponerme a ello y entender su funcionamiento y darle una oportunidad (es importante dar oportunidades) para ver si me sorprende. #Importante ¿Veis que no hay más módulos, nada de mod_fcgid  ni nada por el estilo verdad? Pues atentos.

Hagamos un break para recordar los mods que tenemos en Apache:

  • Prefork. Venía por defecto en Debian 8. Procesos hijo, mod_php. Más estable y compatible con más módulos software que Worker. En caso de ocurrir un problema, tiene mayor capacidad de aislamiento con respecto al resto de procesos hijo.
  • Worker. Procesos hijo y hebras por hijo. PHP corriendo como FastCgi, lo que es importante por el menor consumo de memoria, pero si un hilo falla, afectará al resto, y esto es un problema.
  • Event. Diseñado para atender más peticiones de forma simultánea pasando trabajo de procesamiento a los hilos oyentes, liberando así a los hilos de trabajo para atender nuevas solicitudes.
 Yo era reacio a utilizar Event ya que se basaba en Worker, de forma que el proceso padre es responsable de lanzar procesos hijo. Cada proceso hijo crea un "fixed number" de hilos servidores especificados en la directiva ThreadsPerChild. Es cierto que los hijos oyentes (Listener threads) permanecen a la escucha en la conexión para pasarse trabajo, pero seguí siendo reacio, porque si caía el proceso padre, ya no se lanzaban procesos hijo y eso iba a ocasionar más problemas que otras cosas.

No obstante, documentándome sí vi en este doc de Apache en el que habla sobre cómo Event soluciona el problema que tenía Worker con las conexiones Keep Alive. Y es que un usuario que completa la primera consulta, puede mantener la conexión abierta enviando peticiones extras utilizando el mismo socket y ahorrando una cantidad significando de "gastos generales" (overhead) en crear conexiones TCP. Tradicionalmente ya sabemos que Apache mantenía un proceso/hilo hijo esperando los datos del cliente. Este MPM soluciona este problema usando un Listener Thread dedicado para cada proceso hijo para manejar los Listening sockets.


Así que me puse a tocar un poco el archivo de configuración de Event y me encontré con el MaxRequestWorkers a 150. Antes de nada decir que este MaxRequestWorkers es lo mismo que el tradicional MaxClients, es más, la directoriva MaxClients aún es utilizada. Podéis revisar este doc de Apache para cercioraros.


Como su propio nombre indica, establece el número máximo de peticiones permitidas y como entenderéis, para una web, 150 peticiones (clientes) es algo muy bajo y que por eso, si te dejas esta misconfiguration, normal que después tu web caiga cuando salen las notas de Selectividad tal y como le pasa a la UCO.

150 clientes son pocos, pero no podemos cambiarlo así porque sí, tendremos que cambiar también el valor de la directiva ServerLimit, que en Event es el valor máximo (en combinación con ThreadLimit) de clientes para el tiempo de vida que Apache puede manejar. Debemos tener en cuenta que cambiar este valor y establecerlo de forma que sea mucho más grande de los necesaro, hará que espacio de memoria extra y no utilizado será asignado, y si establecemos valores de ServerLimit y MaxRequestWorkers mayores de lo que el sistema puede manejar, entonces nuestro sistema se resentirá como es lógico.

Existe un truco que es establecer ese valor de MaxClients (o MaxRequestWorkers, como queráis llamarlo, pero yo es que siento nostalgia xD) teniendo en cuenta en Event y Worker que tienes que multiplicar el valor de ServerLimit y ThreadsPerChild y dejar un valor menor que el obtenido (por ejemplo, en el caso de la captura no lo hemos cumplido, ya que 25X16 es 400 y tendríamos que poner menos, por ejemplo 300,pero es un ejemplo). Así lo recomienda IBM, y es un truco, pero tenemos que tener en cuenta otras cuestiones como es la capacidad de nuestra máquina.

Pero antes contemos el problema. El único problema a nivel Hardware que puede afectar a un webserver es la RAM. Un webserver NUNCA tiene que hacer swapping ya que esto incrementa la latencia. Esto provoca que el usuario pare y recargue la página, por lo que incrementa la carga con nuevas peticiones, y es por esta razón que controlar debidamente el MaxClients (o MaxRequestWorkers) es tan importante.

Lo que tenemos que hacer es, en primer lugar, saber cuánta memoria ocupa Apache (recordemos que hemos dicho que el principal problema a nivel hardware para un webserver es la RAM). Para saber esto vamos a utilizar el comando 

ps -ylC apache2 --sort:rss

Al ejecutar este comando nos saldrá una tabla con los campos [S,UID,PID,PPID,C,PRI,NI,RSS,SZ,WCHAN,TTY,TIME,CMD], pues el valor que nos va a interesar será el del campo "SZ", ese es el que contiene el valor de lo que consume nuestro Apache. Una vez que tengamos esto, tenemos que saber cuánta memoria tiene nuestro equipo y cuánta memoria queremos dejar para otros procesos y aplicar la siguiente fórmula

MaxClients=((Total_memoria)*1024 -Espacio_otros_procesos)/SZ

Esto nos sacará el valor de MaxClients que como máximo deberíamos establecer. Por ejemplo, tenemos una máquina con 8GB de RAM y queremos dejar 2GB(2048 MB) para otros procesos. Hemos comprobado que nuestro Apache consume 30 MB, pues lo que hay que hacer está claro

MaxClients=((8*2014)-2048)/30=204.8 clientes

Por lo que más de 204 en la directiva MaxClients no es recomendable, ya que imaginemos que ponemos 400 como antes. Como sabemosque Apache consume 30 MB y el MaxClients está a 400, multiplicamos y nos sale 12000 que son 12GB, y nuestra máquina tiene 8GB, por lo que la swap entra en juego y eso es lo que no queríamos precisamente.

Es por eso que ese truco de MaxClients<ServerLimit*ThreadsPerChild está bien, pero dentro de ese límite establecido en función de la memoria de nuestro equipo.


Ya sabéis que cada cambio, podemos probar si es correcto lanzando systemctl start (y después status) apache2.service y ver si está activo. Insisto mucho con los MaxClients, pero es que haciendo eso teniendo en cuenta la RAM de nuestro sistema, que el MaxClients concuerde con el MaxConnectios de la Base de Datos, un sistema de Caching como Mencached y 3 cosillas más, conseguiremos que nuestro sistema mejore en disponibilidad notablemente.


En el navegador y ejecutando midominio.com/server-status veremos el estado de nuestro server. En este caso lancé solamente un request, pero lo importante es que veáis que estou con el MPM de event.


Por supuesto después está lo básico de no permitir el método TRACE.


Y ¡Por Darth Vader! no dejéis el Timeout a 300, dejadlo a 30,20 o 15 como mucho, que tener un navegador durante 300 segundos conectado cuando no se encuentra la respuesta y se deje todos esos segundos esperando, es un consumo enorme de recursos inútil. Es totalmente useless.

Y ahora viene lo chulo. Configurar nuestro Debian para que tire con libapache2 utilizando mod_fcgid y con PHP_FPM.


Yo voy a atrochar un poco y voy a dejar capturas donde veis que con a2enmod fcgid me indica que ya estaba habilitado.


Insisto, estoy reduciendo mucho, pero podéis seguir este tutorial donde se explica todo el proceso genial.

Decir que mod_fastcgi con PHP_FPM trae más mejoras que el típico Prefork con mod_php a pesar de lo que creía. Mod_fastcgid lo que hace es arrancar un número suficiente de instancias del programa para manejjar peticiones concurrentes y estos programas permanecen corriendo para manejar peticiones extras. Esto hace que sea significativamente más rápido que mod_cgi que está por defecto. Esto, a pesar de sus ventajas, consume bastantes recursos, por lo que es tarea de un sysadmin manejar esta situación.



Nos vamos a cerciorar que toda la sintaxis está correcta y podremos probar nuestro server. En general decir que Debian 9.5 me ha gustado bastante y que utilizar Debian 9 con Apache en mpm_event con libapache2-mod-fcgid y PHP_FPM hará que tu server pinte distinto y en disponibilidad notes bastante los cambios a mejor.

¿Hackeamos el Mundo?

No hay comentarios:

Publicar un comentario

Related Posts Plugin for WordPress, Blogger...

Entrada destacada

El server me sabe a poco.

Soy un fanático del Rock y de Debian . (Creo que voy a inventar Rockbian, que suena bien y todo xD) Llevaba tiempo queriendo unir estos 2 c...