DEV Community

minnogit
minnogit

Posted on

Hardening Apache Reverse Proxy in produzione

Guida completa a timeout, worker e gestione dei carichi applicativi

In un'infrastruttura dove Apache HTTP Server funge sia da frontend (TLS, routing, bilanciamento) che da tramite verso container Docker, la stabilità non dipende dalla potenza dell'hardware, ma dalla coerenza della catena dei timeout, dai limiti del sistema operativo e dal dimensionamento dell'intero stack applicativo.

Questa guida è focalizzata sul caso reale in cui:

  • Apache frontend agisce da reverse proxy e load balancer
  • Il backend applicativo gira in container
  • In alcuni casi Apache è anche il web server dentro il container
  • L’applicazione è PHP (ma i principi restano validi anche per Python o altri stack)

1. Il Sistema Operativo: Preparare il terreno (Systemd)

Prima di configurare Apache, dobbiamo assicurarci che il sistema operativo gli permetta di lavorare.

Sui sistemi moderni come Debian o Ubuntu, il limite di processi e thread per servizio è gestito da systemd tramite i Cgroups.

Il problema

Sotto carico Apache può raggiungere il limite di task e generare errori nei log simili a:

Fork Rejected
Enter fullscreen mode Exit fullscreen mode

La soluzione

Aumentare TasksMax per il servizio Apache.

systemctl edit apache2.service
Enter fullscreen mode Exit fullscreen mode

Inserire:

[Service]
TasksMax=3000
Enter fullscreen mode Exit fullscreen mode

Applicare:

systemctl daemon-reload
systemctl restart apache2
Enter fullscreen mode Exit fullscreen mode

Per un server con 4 GB RAM e ~400 worker, 3000 è un valore equilibrato.


2. Monitoraggio in tempo reale: i comandi “Manometro”

Per capire se il limite è corretto, interroga direttamente i Cgroups:

cat /sys/fs/cgroup/system.slice/apache2.service/pids.current
cat /sys/fs/cgroup/system.slice/apache2.service/pids.max
Enter fullscreen mode Exit fullscreen mode

Se pids.current si avvicina a pids.max, il server inizierà a rifiutare connessioni.

Questo è il primo indicatore reale di saturazione.


3. Il Motore: MPM Event dimensionato per 4GB RAM

Il modulo MPM Event gestisce le connessioni in modo asincrono, evitando che i thread restino bloccati su KeepAlive.

Configurazione:

/etc/apache2/mods-available/mpm_event.conf

<IfModule mpm_event_module>
    ServerLimit              16
    StartServers             3
    ThreadsPerChild          25
    MaxRequestWorkers        400
    MinSpareThreads          25
    MaxSpareThreads          75
    MaxConnectionsPerChild   10000
</IfModule>
Enter fullscreen mode Exit fullscreen mode

Perché questi numeri?

  • 16 processi × 25 thread = 400 richieste simultanee
  • circa 800 MB occupati da Apache
  • RAM restante per PHP, sistema e cache

Se PHP cresce, Apache deve ridursi.


4. La Catena dei Timeout: Sincronia Proxy-Backend

Se proxy e backend non sono coordinati, i worker restano occupati inutilmente.

Regola fondamentale: l’applicazione deve morire prima del proxy.

Parametro Proxy Backend Note
KeepAliveTimeout 3s 5s Il backend aspetta di più
Timeout 60s 65s Ricezione dati
ProxyTimeout 300s Attesa risposta backend
PHP max_execution_time 290s L’app muore prima del proxy

5. Configurazione Globale dei Timeout (operativa)

Creare:

/etc/apache2/conf-available/global-timeouts.conf
Enter fullscreen mode Exit fullscreen mode
KeepAlive On
MaxKeepAliveRequests 100
KeepAliveTimeout 3

Timeout 60
ProxyTimeout 300
Enter fullscreen mode Exit fullscreen mode

Attivare:

a2enconf global-timeouts
systemctl reload apache2
Enter fullscreen mode Exit fullscreen mode

Questo file evita configurazioni duplicate nei VirtualHost.


6. Bilanciamento e Failover Rapido

Il failover lento è uno dei problemi più comuni nei proxy Apache.

Usiamo connectiontimeout per forzare il rilevamento immediato dei nodi down.

<Proxy "balancer://app_cluster">
    BalancerMember "http://node01:8080" route=n1 connectiontimeout=2 retry=30
    BalancerMember "http://node02:8080" route=n2 connectiontimeout=2 retry=30
    ProxySet lbmethod=bybusyness timeout=60
</Proxy>
Enter fullscreen mode Exit fullscreen mode

Con questo:

  • un nodo morto viene escluso in ~2 secondi
  • il traffico migra subito sugli altri

7. Separare traffico veloce e lento

Questa tecnica serve a proteggere le richieste normali da quelle pesanti.

È corretta solo se il backend lento ha risorse dedicate.

# Pool veloce
<Proxy "balancer://app_fast">
    BalancerMember "http://app:8080" connectiontimeout=2
    ProxySet timeout=60
</Proxy>

# Pool lento
<Proxy "balancer://app_slow">
    BalancerMember "http://app_dedicated:8080" connectiontimeout=2
    ProxySet timeout=1200
</Proxy>
Enter fullscreen mode Exit fullscreen mode

Se entrambi puntano allo stesso backend, non serve a nulla.


8. PHP-FPM: il vero limite della capacità

Apache accetta la richiesta, ma PHP la esegue.

Per 4 GB con 2 GB dedicati a PHP:

pm.max_children ≈ RAM_php / memoria_media_script
Enter fullscreen mode Exit fullscreen mode

Configurazione:

/etc/php/8.x/fpm/pool.d/www.conf

pm = dynamic
pm.max_children = 40
pm.start_servers = 10
pm.max_requests = 500
request_terminate_timeout = 300s
Enter fullscreen mode Exit fullscreen mode

Se PHP si satura, Apache sembra lento anche se non lo è.


9. Quando il tuning non basta: strategie architetturali

Il tuning dei timeout migliora la stabilità, ma non cambia il modello di carico.

Le operazioni lunghe dovrebbero diventare asincrone.

Soluzioni tipiche

  • code con Redis
  • code con RabbitMQ
  • job worker separati
  • risposta immediata “presa in carico”

Questo libera i worker Apache in pochi millisecondi.


10. Checklist finale operativa

✔ TasksMax aumentato e verificato
✔ MPM Event dimensionato sulla RAM
✔ Timeout coerenti tra proxy, backend e PHP
✔ Failover rapido con connectiontimeout
✔ Backend lento separato solo se realmente isolato
✔ PHP-FPM dimensionato sulla RAM reale
✔ Monitoraggio periodico dei pids Apache


Conclusione

La stabilità di un reverse proxy Apache non dipende da un singolo parametro, ma dall'allineamento di:

  • limiti del sistema operativo
  • modello di concorrenza di Apache
  • timeout della catena proxy-backend
  • capacità reale dell’applicazione

Quando questi quattro livelli sono coerenti, Apache diventa estremamente stabile anche sotto carico elevato.


Top comments (0)