upstream backend_servers {
least_conn; # Trimite request-ul către serverul cel mai puțin ocupat
server 10.0.0.1:8080 max_fails=3 fail_timeout=30s;
server 10.0.0.2:8080 max_fails=3 fail_timeout=30s;
server 10.0.0.3:8080 max_fails=3 fail_timeout=30s;
}
server {
listen 80;
server_name aplicatie.ro;
location / {
proxy_pass http://backend_servers;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}Salutare. M-am trezit săptămâna asta cu un client care vrea neapărat să migrăm aplicația de pe un singur VPS pe o arhitectură cu trei servere în spate, fiindcă se așteaptă la un val mare de trafic luna viitoare. Recunosc că, deși fac backend de peste zece ani, pe partea de infrastructură hardcore am mers mereu pe chestii simple sau managed, așa că trecerea asta la load balancing manual îmi dă puțin cu virgulă.
Am mai avut un caz acum vreo trei ani, la un proiect cu vreo 12k utilizatori activi, unde am încercat să aruncăm un load balancer în față fără să ne gândim la consecințe. A fost un dezastru. Sesiunile utilizatorilor mureau instant fiindcă request-ul 1 ajungea pe serverul A (unde se crea sesiunea), iar request-ul 2 pe serverul B (care nu știa cine e omul). Ca să nu repetați greșeala mea, am pus cap la cap pașii esențiali pentru o tranziție curată.
1. Load Balancer-ul (Nginx sau Cloud provider?)
Prima tentație e să folosesc un load balancer managed de la DigitalOcean sau AWS. E simplu, dai trei click-uri, plătești 10-15 dolari pe lună și ai scăpat de configurat manual proxy-uri.
Totuși, ca exercițiu și pentru control, se poate pune un VPS mic doar pentru un Nginx configurat ca reverse proxy cu un bloc upstream. Merge super ok pentru load mediu, dar trade-off-ul e evident: dacă pică VPS-ul cu Nginx, pică tot site-ul, deci ai un Single Point of Failure (SPOF). La managed load balancers, cloud providerul se ocupă de redundanță în spate.
2. Partajarea stării (Sesiuni și fișiere)
Aici e buba mare când treci de la un singur server la trei. Aplicația clasică salvează adesea sesiunile pe disc și imaginile încărcate de useri tot local, în /public/uploads. Pe trei servere, asta nu mai merge.
Soluția pe care am aplicat-o:
- Sesiuni în Redis: Am mutat tot ce înseamnă sesiune într-o instanță separată de Redis. Așa, oricare dintre cele 3 servere web poate citi instant starea userului.
- Upload-uri pe S3 sau Cloudflare R2: Am eliminat stocarea locală. Toate upload-urile merg direct în cloud storage, iar în baza de date salvez doar URL-ul public.
3. Gâtuirea bazei de date (Aici intră PgBouncer)
Folosesc PostgreSQL. Dacă fiecare din cele 3 servere de aplicație pornește un pool de conexiuni de, să zicem, 20 de conexiuni active, baza de date o să se trezească instant cu 60 de conexiuni deschise permanent. La primul spike de trafic, Postgres o să înceapă să dea reject-uri din lipsă de resurse.
PgBouncer e sfânt aici. Îl instalezi direct pe serverul cu baza de date, el face connection pooling inteligent la nivel de tranzacție, iar serverele de aplicație se conectează la el ca și cum ar fi baza de date reală. Am economisit cam 35% din memoria RAM a serverului de bază de date doar prin mutarea conexiunilor prin PgBouncer.
4. CDN-ul ca prim scut
Înainte ca vreun request să atingă load balancer-ul, Cloudflare trebuie să fie activ. Un Cloudflare bine configurat, cu cache agresiv pe imagini, CSS și JS, preia cam 60% din load-ul total al serverelor. Practic, cele 3 servere din spate vor procesa doar logica de business brută, nu și livrarea de fișiere statice.
Voi cum ați gestionat prima migrare de genul ăsta? Ați mers pe varianta "roll your own" cu Nginx configurat manual sau ați aruncat direct cu bani în load balancere managed?