Salutare comunitate. Am dat de o belea destul de mare pe partea de infrastructură și am nevoie de niște sfaturi de la cei care s-au lovit de asta la scară reală.
Avem o aplicație Laravel destul de clasică care rulează în prezent pe un singur VPS măricel (8 nuclee, 16GB RAM). Duce destul de bine, avem în jur de 5.000 de utilizatori activi pe zi și totul e stabil. Problema e că clientul tocmai a semnat un contract de marketing masiv și se așteaptă la un val de 10x trafic în următoarele două luni. Directiva a venit scurt și tăios de sus: "Vrem disponibilitate 100%, mutăm totul pe 3 servere cu load balancer în față".
Sincer, n-am mai configurat o arhitectură multi-server de la zero. Am mai folosit Cloudflare pentru DNS și reguli de bază, dar cam atât. Cum împart aplicația asta ca să nu mă trezesc cu sesiuni pierdute și baze de date blocate în prima zi de campanie?
M-am documentat în ultimele nopți și am creionat un plan de atac, dar am mari dubii la câteva capitole critice.
Pasul 1: Load Balancer-ul și coșmarul sesiunilor
Prima chestie: cum împart traficul? Mă gândeam să pun un Nginx ca load balancer (pe un al patrulea server mai mic) sau să las Cloudflare să facă asta direct prin serviciul lor plătit.
Dacă merg pe Nginx clasic cu round-robin, apare problema sesiunilor de utilizator. Laravel le ține acum pe disc. Dacă un user nimerește pe Serverul A și la următorul request pe Serverul B, sistemul îl deloghează pentru că Serverul B nu-i știe sesiunea.
Trade-off-ul e destul de enervant aici. Aș putea folosi ip_hash în Nginx (sticky sessions) ca să trimit mereu același IP pe același server, dar dacă pică Serverul A, toți utilizatorii de pe el sunt delogați instant și pierd coșul de cumpărături. Alternativa corectă ar fi să mut sesiunile în Redis, pe un server separat. Asta înseamnă însă încă o piesă în mișcare pe care trebuie să o monitorizez.
Pasul 2: Postgres și limita de conexiuni
Aici e panica mea cea mai mare. În clipa asta, baza de date (Postgres) rulează pe același server cu aplicația. Dacă sparg aplicația pe 3 servere web, toate se vor conecta la o singură bază de date centrală (pe care o mut pe un VPS dedicat).
La 3 servere web, fiecare cu câte 20-30 de procese PHP-FPM active, o să ating rapid limita de conexiuni din Postgres (max_connections). Am economisit vreo 30% la utilizarea de memorie în teste optimizează query-urile, dar la trafic masiv tot mi-e frică de un blocaj.
Am auzit de PgBouncer ca middleware de pooling. Îl folosește cineva în producție pentru chestii de dimensiunea asta? E greu de configurat în mod transaction? Sau e mai simplu să măresc pur și simplu resursele pe serverul de DB și să las conexiunile directe până când chiar explodează traficul?
Pasul 3: Unde punem fișierele încărcate de useri?
Utilizatorii noștri încarcă PDF-uri și imagini de profil destul de des. Momentan se salvează local în folderul storage. Pe 3 servere, dacă un user încarcă poza pe Serverul 1, Serverul 2 și 3 nu o vor vedea deloc.
Soluția logică pare să fie migrarea către Cloudflare R2 sau AWS S3. R2 pare super atractiv pentru că nu are costuri de egress (trafic de descărcare), dar modificarea codului ca să folosească un driver de cloud storage pentru toate upload-urile vechi s-ar putea să-mi ia o săptămână de refactoring și teste pe care nu prea o am la dispoziție.
Cum ați aborda tranziția asta dacă ați fi în locul meu? Merită să mă complic cu Redis și PgBouncer din prima zi, sau să merg pe o structură mai simplă și să rezolv problemele pe parcurs ce apar?