Platforma za javna upozorenja koja je držala više od 350.000 trajnih WebSocket konekcija i primala oko 65.000 poruka u sekundi postala je nestabilna tokom simulacija hitnih situacija sa visokom konkurentnošću. Obrada JSON-a zasnovana na stablu podigla je alokaciju na oko 14,2 GB/s, što je dovelo do G1GC pauza dužih od 1,8 sekundi (najgori slučaj oko 4,2 sekunde), znatno preko heartbeat prozora od 1 sekunde. Konekcije su istekle masovno, a naknadni talasi ponovnog povezivanja generisali su dodatnu alokaciju: alokacija -> GC pauze -> heartbeat timeout-i -> masovni diskonekti -> reconnect oluja -> nova alokacija
REŠENJE
SWARCS je uklonio alokaciju na izvoru: parsiranje JSON-a u stablo zamenjeno je streaming parsiranjem, a suvišno kopiranje podataka i kreiranje objekata na kritičnoj putanji prijema je smanjeno. G1GC je zatim podešen prema smanjenom profilu alokacije kako bi se održao prostor za rezervu tokom naglih skokova opterećenja. Nije dodat nikakav računski kapacitet.
KLJUČNI ARHITEKTONSKI POMAK
OD
ekstremno kreiranje kratkotrajnih objekata + nepredvidive višesekundne pauze
→
KA
značajno niži pritisak na alokacije + predvidiv GC sa niskom latencijom
ZAKLJUČAK
U ciljnom simulacionom opterećenju: Stopa alokacije memorije: 14,2 GB/s -> 3,8 GB/s, p99 trajanje GC pauze: 1.800+ ms -> < 85 ms, Prekidi WebSocket konekcija: 18,5% -> 0,0%, Reconnect oluje: Ponavljajuće -> Nije primećeno, Iskorišćenost CPU-a: Zasićena osnova -> ~35% niža. Ključna promena bila je uklanjanje nepotrebne alokacije sa kritične putanje izvršavanja, a zatim podešavanje kolektora prema dobijenom opterećenju.
ARHITEKTONSKA ANALIZA
KONTEKST I POSLOVNI UTICAJ
Platforma prosleđuje hitna upozorenja, obaveštenja o
evakuaciji i telemetrijske podatke o opasnostima u realnom
vremenu kroz geografske zone, do mobilnih uređaja,
terenskih terminala i dispečerskih sistema službi za
reagovanje u vanrednim situacijama.
kašnjenje hitnih obaveštenja
zastoj mrežne obrade tokom dugih JVM pauza
masovni prekidi WebSocket konekcija nakon isteka heartbeat rokova
talasi ponovnog povezivanja koji dodatno opterećuju infrastrukturu na ivici mreže
kaskadna degradacija tokom vršnih simulacija vanrednih situacija
Ključna karakteristika bio je mehanizam povratne sprege.
Pauza duža od heartbeat granice mogla je istovremeno da
utiče na veliki broj konekcija. Naknadni pokušaji ponovnog
povezivanja zatim su stvarali dodatno opterećenje u sistemu
koji je već bio pod pritiskom.
POVRATNA PETLJA OTKAZIVANJA
Prekomerna alokacija
|
v
GC pritisak
|
v
Duge STW pauze
|
v
Istek heartbeat roka
|
v
Masovni prekidi veza
|
v
Reconnect oluja
|
v
Dodatna alokacija
|
+----------> GC pritisak
Inženjerski cilj bio je da se povrati predvidivo ponašanje
runtime-a pri postojećoj operativnoj skali, umesto da se
dodatnim ukupnim kapacitetom pokušava apsorbovati ista
neefikasna putanja obrade.
UZROK I FORENZIČKA ANALIZA
Sloj za prijem koristio je Spring Boot, reaktivni WebFlux
i Netty na Java 17 LTS, sa približno 32 GB JVM heap-a
po čvoru, u klasteru od 8 čvorova.
Tokom vršnih simulacija klaster je ispoljavao WebSocket
timeout-e, prekide konekcija i zasićenje CPU-a.
Povećanje infrastrukturnog kapaciteta nije uklonilo
osnovni način otkazivanja: putanja prijema nastavila je
da generiše prekomernu količinu prolaznog posla za svaku
dolazeću poruku.
Dokazi su ukazivali na samopojačavajući mehanizam
otkazivanja:
prekomerna prolazna alokacija povećavala je GC pritisak;
ozbiljne pauze prelazile su heartbeat granicu konekcija;
masovni prekidi stvarali su dodatno opterećenje.
Intervencija je zato morala da obuhvati i dominantni izvor
alokacije i ponašanje kolektora pod nastalim opterećenjem.
Otklanjanje samo simptoma ponovnog povezivanja ostavilo
bi početni izvor pritiska netaknutim.
ARHITEKTONSKI UVID I EVOLUCIJA
Horizontalno skaliranje moglo je da poveća ukupan kapacitet,
ali ne bi uklonilo nepotrebno kreiranje objekata za svaku
dolazeću poruku.
Redizajn je zato obuhvatio dva zasebna cilja:
1. Smanjenje nepotrebne alokacije na kritičnoj putanji prijema.
2. Podešavanje G1GC-a prema nastalom opterećenju i zahtevima za latenciju.
Smanjenje alokacije rešavalo je izvor pritiska. Podešavanje
GC-a uticalo je na ponašanje runtime-a nakon što je taj
pritisak smanjen.
OD MATERIJALIZACIJE STABLA DO SELEKTIVNOG PARSIRANJA
STARI MODEL PRIJEMA
Mrežni payload
|
v
ObjectMapper stablo
deserijalizacija
|
v
Potpun graf objekata
+ privremeni objekti
|
v
Visoka stopa alokacije
14,2 GB/s
|
v
GC pritisak i pauze
|
v
Otkazivanje heartbeat-a
REDIZAJNIRANI PRIJEM
Mrežni payload
|
v
Pooled Netty bafer
|
v
Jackson streaming parser
|
v
Selektivno izdvajanje polja
|
v
Niža stopa alokacije
3,8 GB/s
|
v
G1GC podešen za opterećenje
|
v
Stabilne konekcije
KLJUČNE INŽENJERSKE ODLUKE
održavanje dodatnog rezervnog kapaciteta tokom naleta alokacije
obezbeđivanje dovoljnog kapaciteta za konkurentno sakupljanje u okviru ciljnog opterećenja
smanjenje rizika od neuspeha evakuacije i ozbiljne GC eskalacije
očuvanje responzivnosti aplikacije pod izmerenim opterećenjem
KVANTIFIKOVANI REZULTATI
Stopa alokacije memorije
PRE
14,2 GB/s
POSLE
3,8 GB/s
Smanjenje od 73%
p99 trajanje GC pauze
PRE
1.800+ ms
POSLE
< 85 ms
Smanjenje od 95%+
End-to-end latencija isporuke (p99)
PRE
~2,1 s
POSLE
~310 ms
Unutar ugovornog cilja od 500 ms
Full GC događaji
PRE
9 po testu
POSLE
0 po testu
Nijedan Full GC događaj nije zabeležen nakon promene
Prekidi WebSocket konekcija
PRE
18,5% pod vršnim opterećenjem
POSLE
0,0%
Nisu zabeleženi prekidi konekcija
Reconnect oluje
PRE
Ponavljale su se
POSLE
0 događaja
Nijedan događaj nije zabeležen
Iskorišćenost CPU-a
PRE
Zasićeno početno stanje
POSLE
~35% niža
Povraćen procesni kapacitet
Sve brojke odnose se na ceo klaster i izmerene su tokom
tri testa od po 45 minuta, sa ciljanim simulacionim
opterećenjem za vanredne situacije.
Stopa alokacije pala je sa približno 14,2 GB/s na
3,8 GB/s, što predstavlja smanjenje od oko 73%.
Pri brzini prijema od 65.000 poruka u sekundi, ove stope
odgovaraju približno 218 KB i 58 KB ukupne alokacije
po primljenoj poruci.
To su izvedeni proseci na nivou celog klastera. Oni
kvantifikuju opterećenje alokacijom povezano sa obradom
poruka, a ne zaseban trošak alokacije samog parsera.
p99 trajanje GC pauze smanjeno je sa više od 1,8 sekundi
na manje od 85 ms. Najduža pauza zabeležena nakon promene
iznosila je 112 ms.
Prekidi konekcija smanjeni su sa 18,5% na nula zabeleženih
prekida, a tokom izmerenih testova nakon promene nisu
zabeležene reconnect oluje.
Rezultati su dobijeni tokom simulacija vanrednih situacija
na produkcionoj platformi, a ne tokom stvarne vanredne
situacije. Oni opisuju testirano opterećenje i period
posmatranja; ne garantuju iste rezultate pri drugačijim
obrascima saobraćaja, hardveru, veličini heap-a ili
runtime uslovima.
Otkazi na nivou infrastrukture, kao što je gubitak
mrežnog segmenta, nisu bili obuhvaćeni izmerenom
intervencijom. Otpornost klijentskog ponovnog povezivanja,
uključujući exponential backoff sa jitter-om, predstavlja
komplementarnu meru koja nije bila deo izmerene promene.
Iskorišćenost CPU-a bila je približno 35% niža nakon
intervencije. To je u skladu sa smanjenjem rada povezanog
sa alokacijom i garbage collection-om, kao i sa manjim
brojem prekida konekcija i pratećom obradom rukovanja
konekcijama.
Klaster je povratio procesni kapacitet bez povećanja
računskih resursa.
Merenja pokazuju da je platforma stabilizovana u okviru ciljnog
opterećenja bez dodavanja računskog kapaciteta.
Pritisak alokacije, koji je najvećim delom poticao od obrade JSON-a
u obliku stabla, dostizao je približno 14,2 GB/s, uz GC pauze duže
od 1,8 sekundi.
SWARCS je smanjio alokaciju na kritičnoj putanji prijema zamenom
parsiranja JSON stabla streaming parsiranjem, a zatim podesio G1GC
prema nastalom opterećenju.
Kombinovana intervencija smanjila je pritisak alokacije i poboljšala
uočeno ponašanje runtime-a. Tokom izmerenih testova, prethodni
mehanizam otkazivanja izazvan dugim pauzama više nije dovodio do
reconnect oluja.
INŽENJERSKI DOPRINOS
SWARCS je sproveo runtime forenziku, profilisanje alokacija,
optimizaciju putanje prijema i podešavanje JVM-a prema opterećenju
kako bi stabilizovao platformu.
ODGOVORNOSTI
profilisanje alokacija na putanji prijema visoke propusnosti pomoću JFR-a
identifikacija izgradnje JSON stabla kao jednog od dominantnih izvora alokacije
zamena obrade JSON-a u stablo streaming obradom pomoću JsonParser-a
smanjenje nepotrebnih alokacija i kopiranja mrežnih bafera
uklanjanje nepotrebnog boxing-a primitiva u reprezentacijama na kritičnoj putanji
kontrolisano ponovno korišćenje objekata tamo gde je profilisanje to opravdalo
evaluacija i konfiguracija G1GC-a za nastalo opterećenje
validacija ponašanja kolektora u odnosu na zahteve aplikacije u pogledu heartbeat-a
reprodukcija uslova visoke konkurentnosti sa više od 350.000 aktivnih WebSocket konekcija
validacija prijema pri brzini od približno 65.000 poruka u sekundi
KLJUČNA PORUKA
NE SKALIRAJ HORIZONTALNO DA BI PRIKRIO PRITISAK ALOKACIJE.
PROFILIŠI KRITIČNU PUTANJU.
UKLONI NEPOTREBNU ALOKACIJU.
PODESI KOLEKTOR PREMA IZMERENOM OPTEREĆENJU.
POŠTUJ MREŽNE I APLIKACIONE ROKOVE.
VALIDIRAJ PONAŠANJE RUNTIME-A POD REALISTIČNIM OPTEREĆENJEM.
MERI MEHANIZAM OTKAZIVANJA, A NE SAMO ISKORIŠĆENOST CPU-A.
U JVM sistemima sa visokim stepenom konkurentnosti dodatni hardver
ne rešava nužno mehanizam koji sistem čini nestabilnim.
Kada prolazna alokacija izaziva višesekundne pauze garbage collection-a,
lokalni problem runtime-a može da pređe granicu sistema: propušteni
heartbeat rokovi prekidaju konekcije, a talasi ponovnog povezivanja
stvaraju dodatno opterećenje širom platforme.
Inženjerski zadatak je da se identifikuje i ukloni izvor tog pritiska,
a zatim da se ponašanje kolektora i aplikacije proveri u odnosu na
stvarne zahteve za latenciju.
U ovom slučaju, smanjenje nepotrebne alokacije promenilo je uslove
izvršavanja koji su garbage collection pretvarali u pojačavač
distribuiranog otkazivanja.