# Optimización del consumo de memoria en Apache

En este capítulo se recopilan una serie de buenas prácticas de cara a la optimización del consumo de memoria en Apache.

## Configuración de Locations

Cada *Location* consume memoria en función del tamaño del proyecto, equivalente a lo que consume, por ejemplo, vClient del mismo proyecto, lo que nos puede dar una idea del orden de magnitud que consumirá posteriormente en Apache.

Cada *Worker* cargará en memoria todos los *Location* definidos en el fichero de configuración de Apache.

### Revisión de Location

Por lo tanto, el primer punto para optimizar, como es lógico, será revisar todos los *Location* utilizados para quitar los no utilizados, ya que cada *Worker* cargará todos los *locations* que estén definidos.

### Configurar Location contra la solución más pequeña posible

Como el consumo de memoria depende de la solución, como vimos anteriormente. La forma de optimizar en este punto es apuntar la conexión de vModApache contra la solución más pequeña posible.

Debemos evitar las herencias innecesarias de proyectos que no se utilicen para servir la información a través de Apache.

Para optimizar este comportamiento, recomendamos evitar seleccionar el proyecto que se encuentre en la parte superior de las herencias. Planteamos dos opciones:

1. Utilizar en el *Location* el proyecto de más abajo posible dentro de la herencia que contenga los elementos necesarios.
2. Crear un proyecto de aplicación específico para servir los elementos deseados, que herede solamente lo necesario para la información que se busca.

A continuación, se muestra un ejemplo utilizando vERP con sus respectivos consumos de memoria:

* Cargando la solución completa de vERP.
* Creando un proyecto de aplicación específico que herede el proyecto de datos directamente:

<figure><img src="https://1419534355-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FhGRTr5J3e6YsZ6MYIEDz%2Fuploads%2FDFCG49F1oPkL7WsfpBVV%2Fimage.png?alt=media&#x26;token=5e2be057-83c3-44f1-a051-816428c1a925" alt=""><figcaption></figcaption></figure>

\
Tabla comparativa del consumo de memoria de los ejemplos anteriores:

| Locations | Solución vERP completa | Proyecto de aplicación específico |
| --------- | ---------------------- | --------------------------------- |
| 1         | 248 + 56 MB            | 71 + 56 MB                        |
| 2         | 457 + 56 MB            | 110 + 56 MB                       |
| 4         | 873 + 56 MB            | 181+ 56 MB                        |
| 8         | 1746 + 56 MB           | 321+ 56 MB                        |

Como conclusión, observamos que al utilizar un proyecto de aplicación específico que herede directamente el proyecto de datos, sin heredar el árbol entero de herencias, se reduce significativamente el uso de memoria. Especialmente cuando aumenta también el número de *Location*. Observamos que, con 8 *Location*, se produce una reducción del consumo de memoria de más del 80%.

El consumo del hilo principal de Apache se mantiene estable (56 MB), mientras que la parte variable del consumo de memoria correspondiente a los *Worker* es la que crece en función del tamaño de la solución cargada (de 248 MB bajamos a 71 MB) y el número de *Location*:

* De 1 *Location* a 8 con la solución completa pasamos de 248 MB a 1746 MB.
* De 1 *Location* a 8 con el proyecto de aplicación específico pasamos de 71 MB a 321 MB.

### Location configurado como Modo Server

Al configurar un *Location* en modo estándar, sin `VelneoMode SERVER`, actúa como un vClient utilizando caché, lo que quiere decir que utilizará memoria para consumir la caché en el *Worker* de Apache. Además, recordemos que este modo no soporta multi-instancia, sólo el modo `VelneoMode SERVER` lo soporta.

Al configurar el *Location* como modo Server, con el parámetro `VelneoMode SERVER`, este no utilizará caché. Enviando las peticiones directamente al servidor, con lo que nos ahorramos el consumo correspondiente a la carga de caché que puede llegar hasta los 500MB en función de la memoria disponible.

#### Caché en vModApache

Los enganches generados por vModApache en modo no Server tienen un comportamiento similar al de vClient, por lo cual, también se aplicará el manejo de caché. Este mecanismo mejora los tiempos de ejecución al reutilizar la información almacenada, evitando su reenvío. Sin embargo, también incrementa el uso de memoria debido al almacenamiento de dichos datos.

## Configuración de Apache

### Reducir número de Workers

Cada *Worker* cargará en memoria todos los *Location* definidos, por lo tanto cuantos menos *Workers* se utilicen menos memoria se consumirá, y entonces los *Workers* trabajarán más. Hemos de tener en cuenta que un menor número de *Worker* y alguna de las siguientes configuraciones al reducir el consumo de memoria, también reducirán la capacidad de respuesta y el rendimiento de Apache.

En el ámbito de configuración de Apache, te recomendamos revisar las directivas que manejan este comportamiento.

Estas configuraciones deben aplicarse en el fichero de configuración de Apache. En el caso de Velneo Cloud se configurarán en el fichero **001-default-ssl.conf**, se colocarán fuera y antes del apartado `<VirtualHost>` para que se apliquen a todo el servidor:

**StartServers**

Define el número de Workers que se inician al arrancar Apache.

Para optimizar el consumo de memoria debemos aplicarle el valor mínimo necesario.

Debemos tener en cuenta que, cuando necesite más *Workers*, los creará hasta el número definido por la directiva `ServerLimit`.

Ejemplo:&#x20;

`StartServers 1`

**ServerLimit**

Límite máximo de *Workers* que Apache puede crear.

Teniendo en cuenta que el consumo de memoria es proporcional al número de *Workers* que se estén utilizando, nos conviene utilizar el mínimo necesario para el correcto consumo del servicio.

Ejemplo:

`ServerLimit 8`

### Número de hilos utilizados por cada Worker

Un *Worker* de Apache está formado por un determinado número de hilos que son los que manejan las peticiones. Las configuraciones referentes a estos hilos tendrán un impacto directo en el consumo de memoria, cuantos más hilos tenga el *Worker*, mayor será el consumo de memoria. Observamos las siguientes directivas:

**MinSpareThreads**

Número mínimo de hilos en espera (inactivos) que conservan los *Workers* para atender nuevas conexiones de forma inmediata.

Para reducir el consumo de memoria debes utilizar valores bajos, mínimo 1. Al reducir el número de hilos en espera, el rendimiento puede ser menor al no quedar ya disponible para la respuesta.

Si el tráfico sube, Apache creará nuevos hilos/procesos.

Ejemplo:&#x20;

`MinSpareThreads 1`

**MaxSpareThreads**

Número máximo de hilos inactivos permitidos.

Debe configurarse como la suma de ThreadsPerChild + MinSpareThreads para cumplir con la restricción del MPM de Apache.

Evita que existan demasiados hilos en espera que consuman memoria sin necesidad. Al reducir el número de hilos en espera, el rendimiento puede ser menor al no quedar ya disponible para la respuesta.

Si este valor supera el valor de ThreadsPerChild obligará a mantener más de un Worker activo.

Ejemplo:

`MaxSpareThreads 64`

Siendo ThreadsPerChild = 64 y MinSpareThreads = 1

**ThreadsPerChild**

Cantidad de hilos que puede manejar cada *Worker*.

Debe ajustarse en función de la naturaleza de la aplicación (mientras más concurrencia se necesite, se puede incrementar). Cuanto más alto, más carga de memoria pero no requerirá la construcción de otro *Worker*.

El valor máximo es 64 para un *Worker*.

Ejemplo:&#x20;

`ThreadsPerChild 64`

**MaxRequestWorkers**

Máximo de hilos (*requests*) que Apache atenderá simultáneamente.

Se calcula como ServerLimit x ThreadsPerChild → 8 x 64 = 512.

Ejemplo:

`MaxRequestWorkers 512`

**MaxConnectionsPerChild**

Cantidad de conexiones que cada proceso hijo atenderá antes de reiniciarse.

Forzar una renovación cada cierto número de solicitudes ayuda a prevenir consumos excesivos de memoria a largo plazo.

Debe configurarse un valor no demasiado bajo, ya que aumenta la sobrecarga de crear y destruir procesos con demasiada frecuencia, pero tampoco un valor demasiado alto para que libere memoria la memoria usada a menudo.

En el caso de usar vModApache en modo estándar, no MODESERVER, ayudaría a liberar el uso de memoria caché. Aunque el módulo ya tiene una gestión de memoria en función de la memoria disponible del sistema, cerrar cada ciertas peticiones permitiría poner la caché a cero.

Ejemplo:

`MaxConnectionsPerChild 1000`

**TimeOut**

Determina cuánto tiempo puede mantenerse abierta una conexión antes de desecharla por inactividad o bloqueo.

Debe configurarse con valores adecuados para descartar las conexiones que bloqueen el correcto funcionamiento del sistema pero sin afectar al resto de peticiones.

Ejemplo

`TimeOut 30`

### Ejemplo de configuración

A continuación mostramos un ejemplo de configuración de Apache que puede ayudar a optimizar el uso de memoria:

```apacheconf
<IfModule mpm_worker_module>
StartServers			1
ServerLimit			8
MinSpareThreads			1
MaxSpareThreads			64
ThreadsPerChild			64
MaxRequestWorkers		512
MaxConnectionsPerChild	        1000
TimeOut				30
</IfModule>
```

<br>
