PHP-FPM (FastCGI Process Manager) es la forma estándar de ejecutar PHP en los servidores web modernos. Una configuración de PHP-FPM bien hecha puede marcar la diferencia entre una web lenta y una rápida. En Theory7 vemos con frecuencia que las configuraciones estándar no son óptimas para la carga de trabajo concreta. En esta guía aprenderás a configurar y optimizar PHP-FPM correctamente para obtener el máximo rendimiento.

¿Qué es PHP-FPM?

PHP-FPM gestiona un pool de procesos worker de PHP. Cuando se solicita una página PHP, uno de estos workers atiende la petición. La forma en que se gestionan los workers determina en gran medida el rendimiento de tu web. Esto es crucial, sobre todo en webs con muchas visitas o aplicaciones intensivas.

Ventajas de PHP-FPM:

  • Mejor gestión de recursos que mod_php, de modo que tu servidor aprovecha con más eficiencia los medios disponibles.
  • Aislamiento de procesos posible por web, lo que aumenta la seguridad y la estabilidad.
  • Reinicios ordenados (graceful restarts) sin tiempo de inactividad, algo esencial para las webs que deben estar disponibles de forma continua.
  • Opciones avanzadas de registro, con las que obtienes más información sobre el rendimiento y los posibles problemas.

Configuración del pool

La configuración del pool determina cuántos procesos PHP se ejecutan. Este archivo suele estar en:

/etc/php/8.2/fpm/pool.d/www.conf

Sustituye 8.2 por tu versión de PHP. Es importante adaptar esta configuración a las necesidades concretas de tu aplicación.

Modos de Process Manager

PHP-FPM tiene tres modos:

  • static - número fijo de workers
    pm = static
    pm.max_children = 20

    Lo mejor para servidores dedicados con una carga predecible.
  • dynamic - se escala automáticamente
    pm = dynamic
    pm.max_children = 50
    pm.start_servers = 10
    pm.min_spare_servers = 5
    pm.max_spare_servers = 20

    Lo mejor para la mayoría de las situaciones, sobre todo con un número de visitas variable.
  • ondemand - workers solo cuando hay peticiones
    pm = ondemand
    pm.max_children = 50
    pm.process_idle_timeout = 10s

    Lo mejor para servidores con poco tráfico o memoria limitada.

Cálculo de max_children

El valor de max_children depende de la memoria disponible. Es crucial calcular bien este valor para evitar sobrecargar tu servidor:

max_children = (Beschikbaar RAM - Overig gebruik) / Gem. PHP proces grootte

Ejemplo de cálculo:

  • Servidor con 4 GB de RAM
  • 1 GB para el sistema operativo y la base de datos
  • Proceso PHP medio: 50 MB
  • max_children = 3000 MB / 50 MB = 60

Comprueba el uso medio de memoria por proceso PHP con el siguiente comando:

ps --no-headers -o "rss" -C php-fpm | awk '{ sum+=$1 } END { print sum/NR/1024 " MB" }'

Límites de peticiones

Evita las fugas de memoria renovando los procesos periódicamente. Puedes configurarlo con:

pm.max_requests = 500

Tras 500 peticiones se reinicia el worker. Esto evita que la memoria crezca por culpa de código mal escrito, lo que es crucial para la estabilidad de tu aplicación.

Optimización de php.ini

Además de la configuración del pool, php.ini también es importante para el rendimiento de tus aplicaciones PHP.

Límites de memoria y de ejecución

Configura los límites de memoria y de ejecución según las necesidades de tu aplicación:

memory_limit = 256M
max_execution_time = 300
max_input_time = 300

Ajústalos a tu aplicación. Por ejemplo, WordPress suele necesitar 256M, mientras que las importaciones grandes requieren más memoria.

Límites de subida

Configura los límites de subida para que tu aplicación pueda procesar archivos grandes:

upload_max_filesize = 64M
post_max_size = 64M
max_file_uploads = 20

Atención: post_max_size debe ser igual o mayor que upload_max_filesize.

Configuración de OPcache

OPcache guarda en memoria el código PHP compilado, lo que puede acelerar considerablemente el tiempo de carga de tu aplicación:

opcache.enable = 1
opcache.memory_consumption = 128
opcache.interned_strings_buffer = 16
opcache.max_accelerated_files = 10000
opcache.revalidate_freq = 60
opcache.validate_timestamps = 1
opcache.fast_shutdown = 1

En producción puedes poner validate_timestamps a 0 para ganar velocidad, pero entonces tendrás que vaciar OPcache manualmente cada vez que cambies el código.

Caché de realpath

Para reducir las llamadas al sistema de archivos de las instrucciones include/require, puedes configurar la caché de realpath:

realpath_cache_size = 4M
realpath_cache_ttl = 600

Aplicar la configuración

Después de hacer cambios, debes reiniciar PHP-FPM para que se apliquen los nuevos ajustes:

# Systemd
sudo systemctl restart php8.2-fpm

# O para otras versiones
sudo systemctl restart php7.4-fpm

Comprueba si la configuración es válida con:

sudo php-fpm8.2 -t

Varios pools para varias webs

Para un mejor aislamiento, puedes crear un pool independiente por web. Esto es especialmente útil para proveedores de hosting o desarrolladores que gestionan varios proyectos:

sudo cp /etc/php/8.2/fpm/pool.d/www.conf /etc/php/8.2/fpm/pool.d/mijnsite.conf

En mijnsite.conf, cambia lo siguiente:

[mijnsite]
user = mijnuser
group = mijnuser
listen = /run/php/php8.2-fpm-mijnsite.sock

Configura tu servidor web para que use el socket correcto en cada web, de modo que cada una tenga sus propios recursos y funcione mejor.

Supervisar el estado de PHP-FPM

Activa la página de estado para supervisar tus procesos de PHP-FPM:

pm.status_path = /fpm-status

Configura tu servidor web para que la sirva (solo en local):

location /fpm-status {
fastcgi_pass unix:/run/php/php8.2-fpm.sock;
include fastcgi_params;
allow 127.0.0.1;
deny all;
}

Resolución de problemas

502 Bad Gateway

Esto puede significar que PHP-FPM no se está ejecutando o que el socket está mal configurado. Comprueba el estado con:

sudo systemctl status php8.2-fpm

Rendimiento lento

Si notas que el rendimiento es lento, comprueba si max_children está configurado demasiado bajo. Puedes hacerlo mirando los registros:

sudo tail -f /var/log/php8.2-fpm.log

Busca mensajes como "server reached max_children" para ver si tienes que añadir más workers.

Errores de memoria

Si te encuentras con errores de memoria, plantéate aumentar memory_limit u optimizar tu código para que consuma menos memoria.

¿Necesitas ayuda?

Estamos a tu disposición. ¿Te has atascado con algo o tienes alguna pregunta? Nuestro equipo de soporte te ayuda personalmente con mucho gusto. Envíanos un mensaje a través del sistema de tickets: solemos responder en unas pocas horas y nos gusta pensar contigo en la solución.

¿Buscas hosting WordPress? Mira nuestra oferta.