upstream app_servers {
# Configurație test Nginx Load Balancer
least_conn;
server 10.0.0.11:3000 max_fails=3 fail_timeout=10s;
server 10.0.0.12:3000 max_fails=3 fail_timeout=10s;
server 10.0.0.13:3000 max_fails=3 fail_timeout=10s;
}
server {
listen 80;
server_name app.internal;
location / {
proxy_pass http://app_servers;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
}
}Salutare tuturor. Am dat peste o situație pe care nu am mai gestionat-o cap-coadă în producție și am nevoie de o confirmare de la cei care au trecut deja prin asta. Un client la un proiect cu vreo 12k utilizatori activi zilnic mi-a cerut să trecem de la monolit pe un singur VPS la o arhitectură pe 3 servere de aplicație cu Load Balancer în față.
Cum arată planul actual (și unde tremur)
Aplicația e un Node.js clasic cu PostgreSQL. Până acum, totul rula pe o singură mașină: fișiere uploadate local, sesiuni în memorie, bază de date pe același IP. Evident, dacă pica VPS-ul, pica tot.
Planul meu actual arată cam așa:
- Cloudflare ca CDN și prima linie de apărare pentru asset-uri statice.
- Un Hetzner Load Balancer (sau un Nginx pe o mașină dedicată) care împarte traficul round-robin către cele 3 servere de app.
- Un server separat pentru PostgreSQL cu PgBouncer în fața lui.
- O instanță de Redis pe serverul de DB pentru sesiuni shared și pub/sub.
Sună frumos pe hârtie. Dar când am început să sap în detaliile de implementare, au apărut bubele reale.
Sesiunile, uploads și conexiunile la bază
Prima problemă de care m-am lovit a fost managementul fișierelor încărcate de useri. Până acum aveam un folder local /uploads. Dacă request-ul X ajunge pe Serverul 1 și încarcă o poză de profil, când intră pe Serverul 2 primește 404. Soluția evidentă e un S3-compatible (MinIO sau AWS S3), dar asta înseamnă rescrierea modulului de stocare în cod. Am economisit vreo 40% din timpul de migrare alegând Hetzner Object Storage, dar tot trebuie să testez atent.
A doua chestie: sesiunile. Am mutat stocarea din memorie în Redis. Aici merge brici pe mediu de test, dar m-am lovit de o nedumerire. Merită să activez sticky sessions pe Load Balancer sau e mai sănătos să las aplicația complet stateless și să trag totul din Redis la fiecare request? Din experiența voastră, ce overhead aduce Redis când ai 800-1000 de conexiuni concurente?
A treia barieră e PostgreSQL. Cu 3 servere de aplicație, fiecare având un pool de 20-30 de conexiuni, o să omor repede limitele bazei de date. Am instalat PgBouncer în mod transaction. A scăzut drastic consumul de memorie pe Postgres, dar la un test de stres cu K6 am observat mici spike-uri de latență la query-uri complexe.
Trade-off-ul principal și ce mă frământă
Trade-off-ul e complexitatea operațională. Dacă pica VPS-ul vechi, dădeam un restart și aia era. Acum am 5 noduri separate (LB, 3x App, DB+Redis). Dintr-o dată trebuie să monitorizez 5 mașini, să gestionez loguri centralizate (probabil un stack Vector + Grafana Loki) și să mă asigur că deploy-ul se face fără downtime.
Voi cum ați abordat prima scalare de genul ăsta?
- Ați mers pe LB managed de la furnizor (Hetzner/DigitalOcean) sau v-ați configurat propriul HAProxy/Nginx?
- PgBouncer l-ați pus pe același server cu Postgres sau ca sidecar pe fiecare nod de aplicație?
Orice părere din producție e mai valoroasă decât 10 tutoriale de pe Medium. Mersi fain!